source: trunk/third/at-spi/cspi/spi_event.c @ 18688

Revision 18688, 17.3 KB checked in by ghudson, 21 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r18687, which included commits to RCS files with non-trunk default branches.
Line 
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
27static GSList *_cspi_event_queue = NULL;
28
29/**
30 * SPI_freeAccessibleKeySet:
31 * @keyset: An AccessibleKeyset to free.
32 *
33 * Release the memory used by an AccessibleKeySet.
34 *
35 **/
36void
37SPI_freeAccessibleKeySet (AccessibleKeySet *keyset)
38{
39  int i = 0;   
40  g_free (keyset->keysyms);
41  g_free (keyset->keycodes);
42  while (keyset->keystrings [i])
43    {
44      g_free (keyset->keystrings [i++]);
45    }
46  g_free (keyset->keystrings);
47  g_free (keyset);
48}
49
50/**
51 * SPI_createAccessibleKeySet:
52 * @len: the number of key values in the key set.
53 * @keysyms: a UTF-8 string containing symbolic key values to be matched, or NULL if
54 *           matching is performed against other key values instead.
55 * @keycodes: an array of unsigned short values which are the hardware keycodes
56 *           to be matched, or NULL if the keyset is specified solely by keysyms
57 *           and/or keystrings.
58 * @keystrings: an array of null-terminated character strings which specify key
59 *             name values to match, or NULL if the keyset is specified solely by
60 *             keycodes and/or keysyms.
61 *
62 * Create a new #AccessibleKeySet of a specified length.
63 * A KeySet is used typically to match key event values, and a matches are made
64 * using the following criteria: a match exists with a key event if all non-null
65 * i-th members of the keyset match the key event.
66 * If both keystring and keysym values are NULL, a keycode value match is
67 * forced, thus the match for keysym=0, keycode=0, keystring=NULL is
68 * keycode 0.
69 *
70 * Returns: a pointer to a newly-created #AccessibleKeySet.
71 *
72 **/
73AccessibleKeySet *
74SPI_createAccessibleKeySet (int len, const char *keysyms, short *keycodes,
75                            const char **keystrings)
76{
77  AccessibleKeySet *keyset = g_new0 (AccessibleKeySet, 1);
78  int i, keysym_len = 0;
79  const char *keysym_ptr = keysyms;
80  keyset->len = len;
81  keyset->keysyms = g_new0 (unsigned long, len);
82  keyset->keycodes = g_new0 (unsigned short, len);
83  keyset->keystrings = g_new0 (char *, len);
84  if (keysyms)
85    {
86      keysym_len = g_utf8_strlen (keysyms, -1);
87    }
88  for (i = 0; i < len; ++i)
89    {
90      if (i < keysym_len)
91        {
92          keyset->keysyms [i] = (unsigned long) g_utf8_get_char (keysym_ptr);
93          keysym_ptr = g_utf8_find_next_char (keysym_ptr, NULL);
94        }
95      else
96        {
97          keyset->keysyms [i] = 0;
98        }
99      if (keycodes)
100        {
101          keyset->keycodes [i] = keycodes [i];
102        }
103      if (keystrings)
104        {
105          keyset->keystrings [i] = g_strdup (keystrings [i]);
106        }
107    }
108  return keyset;       
109}
110
111/**
112 * SPI_createAccessibleEventListener:
113 * @callback : an #AccessibleEventListenerCB callback function, or NULL.
114 * @user_data: a pointer to data which will be passed to the callback when invoked.
115 *
116 * Create a new #AccessibleEventListener with a specified (in-process) callback function.
117 *
118 * Returns: a pointer to a newly-created #AccessibleEventListener.
119 *
120 **/
121AccessibleEventListener *
122SPI_createAccessibleEventListener (AccessibleEventListenerCB callback,
123                                   void                     *user_data)
124{
125  AccessibleEventListener *listener = cspi_event_listener_new ();
126  if (callback)
127    {
128      AccessibleEventListener_addCallback (listener, callback, user_data);
129    }
130  return listener;
131}
132
133/**
134 * AccessibleEventListener_addCallback:
135 * @listener: the #AccessibleEventListener instance to modify.
136 * @callback: an #AccessibleEventListenerCB function pointer.
137 * @user_data: a pointer to data which will be passed to the callback when invoked.
138 *
139 * Add an in-process callback function to an existing AccessibleEventListener.
140 * Note that the callback function must live in the same address
141 * space as the AccessibleEventListener implementation code, thus one should not
142 * use this function to attach callbacks to a 'remote' event listener
143 * (that is, one that was not created by a client call to
144 * createAccessibleEventListener ();
145 *
146 * Returns: #TRUE if successful, otherwise #FALSE.
147 *
148 **/
149SPIBoolean
150AccessibleEventListener_addCallback (AccessibleEventListener *listener,
151                                     AccessibleEventListenerCB callback,
152                                     void                     *user_data)
153{
154  cspi_event_listener_add_cb (listener, callback, user_data);
155  return TRUE;
156}
157
158/**
159 * AccessibleEventListener_unref:
160 * @listener: a pointer to the #AccessibleEventListener being operated on.
161 *
162 * Decrements an #AccessibleEventListener's reference count.
163 **/
164void
165AccessibleEventListener_unref (AccessibleEventListener *listener)
166{
167  cspi_event_listener_unref (listener);
168}
169
170/**
171 * AccessibleEventListener_removeCallback:
172 * @listener: the #AccessibleEventListener instance to modify.
173 * @callback: an #AccessibleEventListenerCB function pointer.
174 *
175 * Remove an in-process callback function from an existing AccessibleEventListener.
176 *
177 * Returns: #TRUE if successful, otherwise #FALSE.
178 *
179 **/
180SPIBoolean
181AccessibleEventListener_removeCallback (AccessibleEventListener  *listener,
182                                        AccessibleEventListenerCB callback)
183{
184  cspi_event_listener_remove_cb (listener, callback);
185  return TRUE;
186}
187
188/**
189 * SPI_createAccessibleKeystrokeListener:
190 * @callback : an #AccessibleKeystrokeListenerCB callback function, or NULL.
191 * @user_data: a pointer to data which will be passed to the callback when invoked.
192 *
193 * Create a new #AccessibleKeystrokeListener with a specified callback function.
194 *
195 * Returns: a pointer to a newly-created #AccessibleKeystrokeListener.
196 *
197 **/
198AccessibleKeystrokeListener *
199SPI_createAccessibleKeystrokeListener (AccessibleKeystrokeListenerCB callback,
200                                       void                         *user_data)
201{
202  AccessibleDeviceListener *listener = cspi_device_listener_new ();
203  if (callback)
204    {
205      AccessibleDeviceListener_addCallback (listener, callback, user_data);
206    }
207  return listener;
208}
209
210/**
211 * AccessibleKeystrokeListener_addCallback:
212 * @listener: the #AccessibleKeystrokeListener instance to modify.
213 * @callback: an #AccessibleKeystrokeListenerCB function pointer.
214 * @user_data: a pointer to data which will be passed to the callback when invoked.
215 *
216 * Add an in-process callback function to an existing #AccessibleKeystrokeListener.
217 *
218 * Returns: #TRUE if successful, otherwise #FALSE.
219 *
220 **/
221SPIBoolean
222AccessibleKeystrokeListener_addCallback (AccessibleKeystrokeListener *listener,
223                                         AccessibleKeystrokeListenerCB callback,
224                                         void                         *user_data)
225{
226  cspi_device_listener_add_cb (listener, callback, user_data);
227  return TRUE;
228}
229
230/**
231 * AccessibleKeystrokeListener_removeCallback:
232 * @listener: the #AccessibleKeystrokeListener instance to modify.
233 * @callback: an #AccessibleKeystrokeListenerCB function pointer.
234 *
235 * Remove an in-process callback function from an existing #AccessibleKeystrokeListener.
236 *
237 * Returns: #TRUE if successful, otherwise #FALSE.
238 *
239 **/
240SPIBoolean
241AccessibleKeystrokeListener_removeCallback (AccessibleKeystrokeListener *listener,
242                                            AccessibleKeystrokeListenerCB callback)
243{
244  cspi_device_listener_remove_cb (listener, callback);
245  return TRUE;
246}
247
248/**
249 * AccessibleKeystrokeListener_unref:
250 * @listener: a pointer to the #AccessibleKeystrokeListener being operated on.
251 *
252 * Decrements an #AccessibleKeystrokeListener's reference count.
253 **/
254void
255AccessibleKeystrokeListener_unref (AccessibleKeystrokeListener *listener)
256{
257  cspi_device_listener_unref (listener);
258}
259
260/**
261 * SPI_createAccessibleDeviceListener:
262 * @callback : an #AccessibleDeviceListenerCB callback function, or NULL.
263 * @user_data: a pointer to data which will be passed to the callback when invoked.
264 *
265 * Create a new #AccessibleDeviceListener with a specified callback function.
266 *
267 * Returns: a pointer to a newly-created #AccessibleDeviceListener.
268 *
269 **/
270AccessibleDeviceListener *
271SPI_createAccessibleDeviceListener (AccessibleDeviceListenerCB callback,
272                                       void                         *user_data)
273{
274  AccessibleDeviceListener *listener = cspi_device_listener_new ();
275  if (callback)
276    {
277      AccessibleDeviceListener_addCallback (listener, callback, user_data);
278    }
279  return listener;
280}
281
282/**
283 * AccessibleDeviceListener_addCallback:
284 * @listener: the #AccessibleDeviceListener instance to modify.
285 * @callback: an #AccessibleDeviceListenerCB function pointer.
286 * @user_data: a pointer to data which will be passed to the callback when invoked.
287 *
288 * Add an in-process callback function to an existing #AccessibleDeviceListener.
289 *
290 * Returns: #TRUE if successful, otherwise #FALSE.
291 *
292 **/
293SPIBoolean
294AccessibleDeviceListener_addCallback (AccessibleDeviceListener *listener,
295                                         AccessibleDeviceListenerCB callback,
296                                         void                         *user_data)
297{
298  cspi_device_listener_add_cb (listener, callback, user_data);
299  return TRUE;
300}
301
302/**
303 * AccessibleDeviceListener_removeCallback:
304 * @listener: the #AccessibleDeviceListener instance to modify.
305 * @callback: an #AccessibleDeviceListenerCB function pointer.
306 *
307 * Remove an in-process callback function from an existing #AccessibleDeviceListener.
308 *
309 * Returns: #TRUE if successful, otherwise #FALSE.
310 *
311 **/
312SPIBoolean
313AccessibleDeviceListener_removeCallback (AccessibleDeviceListener *listener,
314                                            AccessibleDeviceListenerCB callback)
315{
316  cspi_device_listener_remove_cb (listener, callback);
317  return TRUE;
318}
319
320/**
321 * AccessibleDeviceListener_unref:
322 * @listener: a pointer to the #AccessibleDeviceListener being operated on.
323 *
324 * Decrements an #AccessibleDeviceListener's reference count.
325 **/
326void
327AccessibleDeviceListener_unref (AccessibleDeviceListener *listener)
328{
329  cspi_device_listener_unref (listener);
330}
331
332static char *
333cspi_internal_event_get_text (const InternalEvent *e)
334{
335  CORBA_any *any;
336  g_return_val_if_fail (e, NULL);
337  g_return_val_if_fail (e->data, NULL);
338  any = (CORBA_any *) e->data;
339  if (CORBA_TypeCode_equivalent (any->_type, TC_CORBA_string, NULL))
340    {
341      return * (char **) any->_value;
342    }
343  else
344    {
345#ifdef EVENT_CONTEXT_DEBUG
346      fprintf (stderr, "requested string, TC is not TC_CORBA_string! (%u)\n",
347               (unsigned) any->_type);
348#endif
349      return NULL;
350    }
351}
352
353static Accessible *
354cspi_internal_event_get_object (const InternalEvent *e)
355{
356  CORBA_any *any;
357
358  g_return_val_if_fail (e, NULL);
359  g_return_val_if_fail (e->data, NULL);
360
361  any = (CORBA_any *) e->data;
362  if (CORBA_TypeCode_equal (any->_type, TC_CORBA_Object, cspi_ev()))
363    return cspi_object_take (* (CORBA_Object *) any->_value);
364  else
365    return NULL;
366}
367
368/**
369 * AccessibleTextChangedEvent_getChangeString:
370 * @event: a pointer to the #AccessibleEvent being queried.
371 *
372 * Queries an #AccessibleEvent of type "object:text-changed",
373 *         returning the text inserted or deleted.
374 *
375 * Returns: a UTF-8 text string indicating the text inserted,
376 *          deleted, or substituted by this event.
377 **/
378char *
379AccessibleTextChangedEvent_getChangeString (const AccessibleEvent *e)
380{
381  const InternalEvent *foo = (InternalEvent *) e;
382  /* TODO: check the event type? expensive... */
383  return cspi_internal_event_get_text (foo);
384}
385
386/**
387 * AccessibleTextSelectionChangedEvent_getSelectionString:
388 * @event: a pointer to the #AccessibleEvent being queried.
389 *
390 * Queries an #AccessibleEvent of type "object:text-selection-changed",
391 *         returning the newly added, removed, or modified selection string.
392 *
393 * Returns: a UTF-8 text string indicating the recently changed selection.
394 **/
395char *
396AccessibleTextSelectionChangedEvent_getSelectionString (const AccessibleEvent *e)
397{
398  const InternalEvent *foo = (InternalEvent *) e;
399  /* TODO: check the event type? expensive... */
400  return cspi_internal_event_get_text (foo);
401}
402
403/**
404 * AccessibleWindowEvent_getTitleString:
405 * @event: a pointer to the #AccessibleEvent being queried.
406 *
407 * Queries an #AccessibleEvent of type "window:",
408 *         returning the window title.
409 *
410 * Returns: a UTF-8 text string representing the title of the
411 *         recently changed window.
412 **/
413char *
414AccessibleWindowEvent_getTitleString (const AccessibleEvent *e)
415{
416  const InternalEvent *foo = (InternalEvent *) e;
417  /* TODO: check the event type? expensive... */
418  return cspi_internal_event_get_text (foo);
419}
420
421/**
422 * AccessibleChildChangedEvent_getChildAccessible:
423 * @event: a pointer to the #AccessibleEvent being queried.
424 *
425 * Queries an #AccessibleEvent of type "object:children_changed"
426 *         to get a reference to the changed #Accessible.
427 *         Note that context #Accessibles are not guaranteed to outlive
428 *         event delivery, in which case this call may return %NULL
429 *         even if the object existed at the time of dispatch.
430 *
431 * Returns: the context #Accessible for the event, or %NULL if
432 *          there is no longer a valid context #Accessible
433 *          object for the event.
434 **/
435Accessible *
436AccessibleChildChangedEvent_getChildAccessible (const AccessibleEvent *e)
437{
438  const InternalEvent *foo = (InternalEvent *) e;
439  return (Accessible *) cspi_internal_event_get_object (foo);
440}
441
442/**
443 * AccessibleParentChangedEvent_getParentAccessible:
444 * @event: a pointer to the #AccessibleEvent being queried.
445 *
446 * Queries an #AccessibleEvent of type "object:parent_changed"
447 *         to get a reference to the changed #Accessible.
448 *         Note that context #Accessibles are not guaranteed to outlive
449 *         event delivery, in which case this call may return %NULL
450 *         even if the object existed at the time of dispatch.
451 *
452 * Returns: an #Accessible pointer representing the new parent object.
453 **/
454Accessible *
455AccessibleParentChangedEvent_getParentAccessible (const AccessibleEvent *e)
456{
457  const InternalEvent *foo = (InternalEvent *) e;
458  return (Accessible *) cspi_internal_event_get_object (foo);
459}
460
461/** NEED TO DOCUMENT THESE **/
462
463Accessible *
464AccessibleActiveDescendantChangedEvent_getActiveDescendant (const AccessibleEvent *e)
465{
466  const InternalEvent *foo = (InternalEvent *) e;
467  return (Accessible *) cspi_internal_event_get_object (foo);
468}
469
470Accessible *
471AccessibleTableSummaryChangedEvent_getSummaryAccessible (const AccessibleEvent *e)
472{
473  const InternalEvent *foo = (InternalEvent *) e;
474  return (Accessible *) cspi_internal_event_get_object (foo);
475}
476
477Accessible *
478AccessibleTableHeaderChangedEvent_getHeaderAccessible (const AccessibleEvent *e)
479{
480  return NULL;
481}
482
483
484char *
485AccessibleTableCaptionChangedEvent_getCaptionString (const AccessibleEvent *e)
486{
487  return NULL;
488}
489
490char *
491AccessibleTableRowDescriptionChangedEvent_getDescriptionString (const AccessibleEvent *e)
492{
493  return NULL;
494}
495
496char *
497AccessibleTableColumnDescriptionChangedEvent_getDescriptionString (const AccessibleEvent *e)
498{
499  return NULL;
500}
501
502char *
503AccessibleDescriptionChangedEvent_getDescriptionString (const AccessibleEvent *e)
504{
505  return NULL;
506}
507
508static gint
509cspi_event_compare (gconstpointer p1, gconstpointer p2)
510{
511  const InternalEvent *e1 = p1, *e2 = p2;
512  return (gint) ((long) e2->id  - (long) e1->id);
513}
514
515static InternalEvent *
516cspi_internal_event_lookup (const InternalEvent *e)
517{
518  InternalEvent *internal = NULL;
519  GSList *p =
520    g_slist_find_custom (_cspi_event_queue, e, cspi_event_compare);
521  if (p)
522    internal = p->data;
523  return internal;
524}
525
526static const InternalEvent *
527cspi_internal_event_check (const AccessibleEvent *e)
528{
529  InternalEvent *internal = (InternalEvent *) e;
530  if (internal->magic == SPI_INTERNAL_EVENT_MAGIC)
531    return internal;
532  else
533    return NULL;
534}
535
536static InternalEvent *
537cspi_internal_event_add (const InternalEvent *e)
538{
539  _cspi_event_queue = g_slist_prepend (_cspi_event_queue, (gpointer) e);
540  return (InternalEvent *) e;
541}
542
543static void
544cspi_internal_event_remove (const InternalEvent *e)
545{
546  GSList *link = g_slist_find_custom (_cspi_event_queue, e, cspi_event_compare);
547  if (link)
548    _cspi_event_queue = g_slist_remove_link (_cspi_event_queue, link);
549}
550
551char *
552AccessibleNameChangedEvent_getNameString (const AccessibleEvent *e)
553{
554  return NULL;
555}
556
557SPIBoolean
558AccessibleEvent_ref (const AccessibleEvent *e)
559{
560  const InternalEvent *private = cspi_internal_event_check (e);
561  if (private)
562    {
563      InternalEvent *event = cspi_internal_event_lookup (private);
564      /*
565       * put event in the cache if it's not there already,
566       * and increment refcount
567       */
568      if (!event)
569        {
570          event = cspi_internal_event_add (private);
571        }
572      event->ref_count++;
573      return TRUE;
574    }
575  else
576    return FALSE;
577}
578
579void
580AccessibleEvent_unref (const AccessibleEvent *e)
581{
582  const InternalEvent *private = cspi_internal_event_check (e);
583  /* decrement refcount and remove if appropriate */
584  if (private)
585    {
586      InternalEvent *event = cspi_internal_event_lookup (private);
587      if (event)
588        {
589          event->ref_count--;
590          if (event->ref_count < 1)
591            cspi_internal_event_remove (event);
592        }
593    }
594}
Note: See TracBrowser for help on using the repository browser.