974ce411a71a0b70a476bb0a6d79cb26d967b8b0
[platform/core/uifw/at-spi2-atk.git] / cspi / spi_event.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2001, 2002 Sun Microsystems Inc.,
6  * Copyright 2001, 2002 Ximian, 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 <cspi/spi-private.h>
25 #include <cspi/bonobo/cspi-bonobo-listener.h>
26
27 /**
28  * SPI_freeAccessibleKeySet:
29  * @keyset: An AccessibleKeyset to free.
30  *
31  * Release the memory used by an AccessibleKeySet.
32  *
33  **/
34 void
35 SPI_freeAccessibleKeySet (AccessibleKeySet *keyset)
36 {
37   int i = 0;    
38   g_free (keyset->keysyms);
39   g_free (keyset->keycodes);
40   while (keyset->keystrings [i])
41     {
42       g_free (keyset->keystrings [i++]);
43     }
44   g_free (keyset->keystrings);
45   g_free (keyset);
46 }
47
48 /**
49  * SPI_createAccessibleKeySet:
50  * @len: the number of key values in the key set.
51  * @keysyms: a UTF-8 string containing symbolic key values to be matched, or NULL if
52  *           matching is performed against other key values instead.
53  * @keycodes: an array of unsigned short values which are the hardware keycodes
54  *           to be matched, or NULL if the keyset is specified solely by keysyms
55  *           and/or keystrings.
56  * @keystrings: an array of null-terminated character strings which specify key
57  *             name values to match, or NULL if the keyset is specified solely by
58  *             keycodes and/or keysyms.
59  *
60  * Create a new #AccessibleKeySet of a specified length.
61  * A KeySet is used typically to match key event values, and a matches are made
62  * using the following criteria: a match exists with a key event if all non-null
63  * i-th members of the keyset match the key event.
64  * If both keystring and keysym values are NULL, a keycode value match is
65  * forced, thus the match for keysym=0, keycode=0, keystring=NULL is
66  * keycode 0.
67  *
68  * Returns: a pointer to a newly-created #AccessibleKeySet.
69  *
70  **/
71 AccessibleKeySet *
72 SPI_createAccessibleKeySet (int len, const char *keysyms, short *keycodes,
73                             const char **keystrings)
74 {
75   AccessibleKeySet *keyset = g_new0 (AccessibleKeySet, 1);
76   int i, keysym_len = 0;
77   const char *keysym_ptr = keysyms;
78   keyset->len = len;
79   keyset->keysyms = g_new0 (unsigned long, len);
80   keyset->keycodes = g_new0 (unsigned short, len);
81   keyset->keystrings = g_new0 (char *, len);
82   if (keysyms)
83     {
84       keysym_len = g_utf8_strlen (keysyms, -1);
85     }
86   for (i = 0; i < len; ++i)
87     {
88       if (i < keysym_len)
89         {
90           keyset->keysyms [i] = (unsigned long) g_utf8_get_char (keysym_ptr);
91           keysym_ptr = g_utf8_find_next_char (keysym_ptr, NULL);
92         }
93       else
94         {
95           keyset->keysyms [i] = 0;
96         }
97       if (keycodes)
98         {
99           keyset->keycodes [i] = keycodes [i];
100         }
101       if (keystrings)
102         {
103           keyset->keystrings [i] = g_strdup (keystrings [i]);
104         }
105     }
106   return keyset;        
107 }
108
109 /**
110  * SPI_createAccessibleEventListener:
111  * @callback : an #AccessibleEventListenerCB callback function, or NULL.
112  * @user_data: a pointer to data which will be passed to the callback when invoked.
113  *
114  * Create a new #AccessibleEventListener with a specified (in-process) callback function.
115  *
116  * Returns: a pointer to a newly-created #AccessibleEventListener.
117  *
118  **/
119 AccessibleEventListener *
120 SPI_createAccessibleEventListener (AccessibleEventListenerCB callback,
121                                    void                     *user_data)
122 {
123   AccessibleEventListener *listener = cspi_event_listener_new ();
124   if (callback)
125     {
126       AccessibleEventListener_addCallback (listener, callback, user_data);
127     }
128   return listener;
129 }
130
131 /**
132  * AccessibleEventListener_addCallback:
133  * @listener: the #AccessibleEventListener instance to modify.
134  * @callback: an #AccessibleEventListenerCB function pointer.
135  * @user_data: a pointer to data which will be passed to the callback when invoked.
136  *
137  * Add an in-process callback function to an existing AccessibleEventListener.
138  * Note that the callback function must live in the same address
139  * space as the AccessibleEventListener implementation code, thus one should not
140  * use this function to attach callbacks to a 'remote' event listener
141  * (that is, one that was not created by a client call to
142  * createAccessibleEventListener ();
143  *
144  * Returns: #TRUE if successful, otherwise #FALSE.
145  *
146  **/
147 SPIBoolean
148 AccessibleEventListener_addCallback (AccessibleEventListener *listener,
149                                      AccessibleEventListenerCB callback,
150                                      void                     *user_data)
151 {
152   cspi_event_listener_add_cb (listener, callback, user_data);
153   return TRUE;
154 }
155
156 /**
157  * AccessibleEventListener_unref:
158  * @listener: a pointer to the #AccessibleEventListener being operated on.
159  *
160  * Decrements an #AccessibleEventListener's reference count.
161  **/
162 void
163 AccessibleEventListener_unref (AccessibleEventListener *listener)
164 {
165   cspi_event_listener_unref (listener);
166 }
167
168 /**
169  * AccessibleEventListener_removeCallback:
170  * @listener: the #AccessibleEventListener instance to modify.
171  * @callback: an #AccessibleEventListenerCB function pointer.
172  *
173  * Remove an in-process callback function from an existing AccessibleEventListener.
174  *
175  * Returns: #TRUE if successful, otherwise #FALSE.
176  *
177  **/
178 SPIBoolean
179 AccessibleEventListener_removeCallback (AccessibleEventListener  *listener,
180                                         AccessibleEventListenerCB callback)
181 {
182   cspi_event_listener_remove_cb (listener, callback);
183   return TRUE;
184 }
185
186 /**
187  * SPI_createAccessibleKeystrokeListener:
188  * @callback : an #AccessibleKeystrokeListenerCB callback function, or NULL.
189  * @user_data: a pointer to data which will be passed to the callback when invoked.
190  *
191  * Create a new #AccessibleKeystrokeListener with a specified callback function.
192  *
193  * Returns: a pointer to a newly-created #AccessibleKeystrokeListener.
194  *
195  **/
196 AccessibleKeystrokeListener *
197 SPI_createAccessibleKeystrokeListener (AccessibleKeystrokeListenerCB callback,
198                                        void                         *user_data)
199 {
200   AccessibleDeviceListener *listener = cspi_device_listener_new ();
201   if (callback)
202     {
203       AccessibleDeviceListener_addCallback (listener, callback, user_data);
204     }
205   return listener;
206 }
207
208 /**
209  * AccessibleKeystrokeListener_addCallback:
210  * @listener: the #AccessibleKeystrokeListener instance to modify.
211  * @callback: an #AccessibleKeystrokeListenerCB function pointer.
212  * @user_data: a pointer to data which will be passed to the callback when invoked.
213  *
214  * Add an in-process callback function to an existing #AccessibleKeystrokeListener.
215  *
216  * Returns: #TRUE if successful, otherwise #FALSE.
217  *
218  **/
219 SPIBoolean
220 AccessibleKeystrokeListener_addCallback (AccessibleKeystrokeListener *listener,
221                                          AccessibleKeystrokeListenerCB callback,
222                                          void                         *user_data)
223 {
224   cspi_device_listener_add_cb (listener, callback, user_data);
225   return TRUE;
226 }
227
228 /**
229  * AccessibleKeystrokeListener_removeCallback:
230  * @listener: the #AccessibleKeystrokeListener instance to modify.
231  * @callback: an #AccessibleKeystrokeListenerCB function pointer.
232  *
233  * Remove an in-process callback function from an existing #AccessibleKeystrokeListener.
234  *
235  * Returns: #TRUE if successful, otherwise #FALSE.
236  *
237  **/
238 SPIBoolean
239 AccessibleKeystrokeListener_removeCallback (AccessibleKeystrokeListener *listener,
240                                             AccessibleKeystrokeListenerCB callback)
241 {
242   cspi_device_listener_remove_cb (listener, callback);
243   return TRUE;
244 }
245
246 /**
247  * AccessibleKeystrokeListener_unref:
248  * @listener: a pointer to the #AccessibleKeystrokeListener being operated on.
249  *
250  * Decrements an #AccessibleKeystrokeListener's reference count.
251  **/
252 void
253 AccessibleKeystrokeListener_unref (AccessibleKeystrokeListener *listener)
254 {
255   cspi_device_listener_unref (listener);
256 }
257
258 /**
259  * SPI_createAccessibleDeviceListener:
260  * @callback : an #AccessibleDeviceListenerCB callback function, or NULL.
261  * @user_data: a pointer to data which will be passed to the callback when invoked.
262  *
263  * Create a new #AccessibleDeviceListener with a specified callback function.
264  *
265  * Returns: a pointer to a newly-created #AccessibleDeviceListener.
266  *
267  **/
268 AccessibleDeviceListener *
269 SPI_createAccessibleDeviceListener (AccessibleDeviceListenerCB callback,
270                                        void                         *user_data)
271 {
272   AccessibleDeviceListener *listener = cspi_device_listener_new ();
273   if (callback)
274     {
275       AccessibleDeviceListener_addCallback (listener, callback, user_data);
276     }
277   return listener;
278 }
279
280 /**
281  * AccessibleDeviceListener_addCallback:
282  * @listener: the #AccessibleDeviceListener instance to modify.
283  * @callback: an #AccessibleDeviceListenerCB function pointer.
284  * @user_data: a pointer to data which will be passed to the callback when invoked.
285  *
286  * Add an in-process callback function to an existing #AccessibleDeviceListener.
287  *
288  * Returns: #TRUE if successful, otherwise #FALSE.
289  *
290  **/
291 SPIBoolean
292 AccessibleDeviceListener_addCallback (AccessibleDeviceListener *listener,
293                                          AccessibleDeviceListenerCB callback,
294                                          void                         *user_data)
295 {
296   cspi_device_listener_add_cb (listener, callback, user_data);
297   return TRUE;
298 }
299
300 /**
301  * AccessibleDeviceListener_removeCallback:
302  * @listener: the #AccessibleDeviceListener instance to modify.
303  * @callback: an #AccessibleDeviceListenerCB function pointer.
304  *
305  * Remove an in-process callback function from an existing #AccessibleDeviceListener.
306  *
307  * Returns: #TRUE if successful, otherwise #FALSE.
308  *
309  **/
310 SPIBoolean
311 AccessibleDeviceListener_removeCallback (AccessibleDeviceListener *listener,
312                                             AccessibleDeviceListenerCB callback)
313 {
314   cspi_device_listener_remove_cb (listener, callback);
315   return TRUE;
316 }
317
318 /**
319  * AccessibleDeviceListener_unref:
320  * @listener: a pointer to the #AccessibleDeviceListener being operated on.
321  *
322  * Decrements an #AccessibleDeviceListener's reference count.
323  **/
324 void
325 AccessibleDeviceListener_unref (AccessibleDeviceListener *listener)
326 {
327   cspi_device_listener_unref (listener);
328 }
329
330 static char *
331 cspi_internal_event_get_text (const InternalEvent *e)
332 {
333   CORBA_any *any;
334   g_return_val_if_fail (e, NULL);
335   g_return_val_if_fail (e->data, NULL);
336   any = (CORBA_any *) e->data;
337   if (CORBA_TypeCode_equivalent (any->_type, TC_CORBA_string, NULL)) 
338     {
339       return * (char **) any->_value;
340     } 
341   else
342     {
343 #ifdef EVENT_CONTEXT_DEBUG
344       fprintf (stderr, "requested string, TC is not TC_CORBA_string! (%u)\n",
345                (unsigned) any->_type);
346 #endif
347       return NULL;
348     }
349 }
350
351 static char *
352 cspi_internal_event_get_object (const InternalEvent *e)
353 {
354   CORBA_any *any;
355   g_return_val_if_fail (e, NULL);
356   g_return_val_if_fail (e->data, NULL);
357   any = (CORBA_any *) e->data;
358   if (any->_type == TC_CORBA_Object) 
359     return cspi_object_add (* (CORBA_Object *) any->_value);
360   else 
361     return NULL;
362 }
363
364
365 /**
366  * AccessibleTextChangedEvent_getChangeString:
367  * @event: a pointer to the #AccessibleEvent being queried.
368  *
369  * Queries an #AccessibleEvent of type "object:text-changed", 
370  *         returning the text inserted or deleted.
371  *
372  * Returns: a UTF-8 text string indicating the text inserted,
373  *          deleted, or substituted by this event.
374  **/
375 char *
376 AccessibleTextChangedEvent_getChangeString (const AccessibleEvent *e)
377 {
378   InternalEvent *foo = (InternalEvent *) e;
379   /* TODO: check the event type? expensive... */
380   return cspi_internal_event_get_text (e);
381 }
382
383 /**
384  * AccessibleChildChangedEvent_getChildAccessible:
385  * @event: a pointer to the #AccessibleEvent being queried.
386  *
387  * Queries an #AccessibleEvent of type "object:children_changed"
388  *         to get a reference to the changed #Accessible.
389  *         Note that context #Accessibles are not guaranteed to outlive
390  *         event delivery, in which case this call may return %NULL
391  *         even if the object existed at the time of dispatch.
392  *
393  * Returns: the context #Accessible for the event, or %NULL if
394  *          there is no longer a valid context #Accessible 
395  *          object for the event.
396  **/
397 Accessible *
398 AccessibleChildChangedEvent_getChildAccessible (const AccessibleEvent *e)
399 {
400   InternalEvent *foo = (InternalEvent *) e;
401   return cspi_internal_event_get_object (e);
402 }
403