Added simple scanning to the virtual keyboard demo, to show one way to
[platform/core/uifw/at-spi2-atk.git] / cspi / spi_registry.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2001 Sun Microsystems Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include <cspi/spi-private.h>
24
25 /*
26  *
27  * Global functions serviced by the registry
28  *
29  */
30
31 /* static stuff used only by registry C bindings */
32 static GList *key_listeners = NULL;
33 static Display *display = NULL;
34
35 /**
36  * registerGlobalEventListener:
37  * @listener: the #AccessibleEventListener to be registered against an
38  *            event type.
39  * @eventType: a character string indicating the type of events for which
40  *            notification is requested.  Format is
41  *            EventClass:major_type:minor_type:detail
42  *            where all subfields other than EventClass are optional.
43  *            EventClasses include "object", "window", "mouse",
44  *            and toolkit events (e.g. "Gtk", "AWT").
45  *            Examples: "focus:", "Gtk:GtkWidget:button_press_event".
46  *
47  * Legal object event types:
48  *
49  *    (property change events)
50  *
51  *            object:property-change
52  *            object:property-change:accessible-name
53  *            object:property-change:accessible-state
54  *            object:property-change:accessible-description
55  *            object:property-change:accessible-parent
56  *            object:property-change:accessible-value
57  *            object:property-change:accessible-role
58  *            object:property-change:accessible-table-caption
59  *            object:property-change:accessible-table-column-description
60  *            object:property-change:accessible-table-column-header
61  *            object:property-change:accessible-table-row-description
62  *            object:property-change:accessible-table-row-header
63  *            object:property-change:accessible-table-summary
64  *
65  *    (other object events)
66  *
67  *            object:children-changed
68  *            object:visible-data-changed
69  *            object:selection-changed
70  *            object:text-selection-changed
71  *            object:text-changed
72  *            object:text-caret-moved
73  *            object:row-inserted
74  *            object:row-reordered
75  *            object:row-deleted
76  *            object:column-inserted
77  *            object:column-reordered
78  *            object:column-deleted
79  *            object:model-changed
80  *
81  * NOTE: this string may be UTF-8, but should not contain byte value 56
82  *            (ascii ':'), except as a delimiter, since non-UTF-8 string
83  *            delimiting functions are used internally.
84  *            In general, listening to
85  *            toolkit-specific events is not recommended.
86  *
87  * Add an in-process callback function to an existing AccessibleEventListener.
88  *
89  * Returns: #TRUE if successful, otherwise #FALSE.
90  *
91  **/
92 boolean
93 registerGlobalEventListener (AccessibleEventListener *listener,
94                              char *eventType)
95 {
96   boolean retval;
97
98   Accessibility_Registry_registerGlobalEventListener (
99                          spi_registry (),
100                          (Accessibility_EventListener)
101                             bonobo_object_corba_objref (bonobo_object (listener)),
102                          eventType,
103                          spi_ev ());
104
105   retval = !spi_exception ();
106  
107   return retval;
108 }
109
110 /**
111  * deregisterGlobalEventListenerAll:
112  * @listener: the #AccessibleEventListener to be registered against
113  *            an event type.
114  *
115  * deregisters an AccessibleEventListener from the registry, for all
116  *            event types it may be listening to.
117  *
118  * Returns: #TRUE if successful, otherwise #FALSE.
119  *
120  **/
121 boolean
122 deregisterGlobalEventListenerAll (AccessibleEventListener *listener)
123 {
124   Accessibility_Registry_deregisterGlobalEventListenerAll (
125                          spi_registry (),
126                          (Accessibility_EventListener)
127                             CORBA_Object_duplicate (
128                                     bonobo_object_corba_objref (
129                                             bonobo_object (listener)), spi_ev ()),
130                          spi_ev ());
131
132   return !spi_exception ();
133 }
134 /**
135  * deregisterGlobalEventListener:
136  * @listener: the #AccessibleEventListener registered against an event type.
137  * @eventType: a string specifying the event type for which this
138  *             listener is to be deregistered.
139  *
140  * deregisters an AccessibleEventListener from the registry, for a specific
141  *             event type.
142  *
143  * Returns: #TRUE if successful, otherwise #FALSE.
144  *
145  **/
146 boolean
147 deregisterGlobalEventListener (AccessibleEventListener *listener,
148                                char *eventType)
149 {
150   Accessibility_Registry_deregisterGlobalEventListener (
151           spi_registry (),
152           (Accessibility_EventListener)
153           CORBA_Object_duplicate (
154                   bonobo_object_corba_objref (bonobo_object (listener)), spi_ev ()),
155           (CORBA_char *) eventType,
156           spi_ev ());
157
158   return !spi_exception ();
159 }
160
161 /**
162  * getDesktopCount:
163  *
164  * Get the number of virtual desktops.
165  * NOTE: currently multiple virtual desktops are not implemented, this
166  *       function always returns '1'.
167  *
168  * Returns: an integer indicating the number of active virtual desktops.
169  *
170  **/
171 int
172 getDesktopCount ()
173 {
174   return Accessibility_Registry_getDesktopCount (
175           spi_registry (), spi_ev ());
176 }
177
178 /**
179  * getDesktop:
180  * @i: an integer indicating which of the accessible desktops is to be returned.
181  *
182  * Get the virtual desktop indicated by index @i.
183  * NOTE: currently multiple virtual desktops are not implemented, this
184  *       function always returns '1'.
185  *
186  * Returns: a pointer to the 'i-th' virtual desktop's #Accessible representation.
187  *
188  **/
189 Accessible*
190 getDesktop (int i)
191 {
192   return spi_object_add (Accessibility_Registry_getDesktop (spi_registry (), (CORBA_short) i, spi_ev ()));
193 }
194
195 /**
196  * getDesktopList:
197  * @list: a pointer to an array of #Accessible objects.
198  *
199  * Get the list of virtual desktops.  On return, @list will point
200  *     to a newly-created array of virtual desktop pointers.
201  *     It is the responsibility of the caller to free this array when
202  *     it is no longer needed.
203  *
204  * Not Yet Implemented : this implementation always returns a single
205  * #Accessible desktop.
206  *
207  * Returns: an integer indicating how many virtual desktops have been
208  *          placed in the list pointed to by parameter @list.
209  **/
210 int
211 getDesktopList (Accessible **list)
212 {
213   *list = NULL;
214   return 0;
215 }
216
217 static gboolean
218 key_event_source_func (void *p)
219 {
220   GList *listeners = (GList *)p;
221   XEvent *x_event = g_new0 (XEvent, 1);
222   while (XPending (display))
223     {
224       XNextEvent (display, x_event);
225       while (listeners)
226         {
227         /* if the listener mask matches, notify it*/
228           if (1)
229             {
230               ;   
231             }
232         }
233     }
234   return TRUE;
235 }
236
237 /**
238  * registerAccessibleKeystrokeListener:
239  * @listener:  a pointer to the #AccessibleKeystrokeListener for which
240  *             keystroke events are requested.
241  * @keys:      a pointer to the #AccessibleKeySet indicating which
242  *             keystroke events are requested, or #SPI_KEYSET_ALL_KEYS.
243  * @modmask:   an #AccessibleKeyMaskType mask indicating which
244  *             key event modifiers must be set in combination with @keys,
245  *             events will only be reported for key events for which all
246  *             modifiers in @modmask are set.  If you wish to listen for
247  *             events with multiple modifier combinations you must call
248  *             registerAccessibleKeystrokeListener() once for each combination.
249  * @eventmask: an #AccessibleKeyMaskType mask indicating which
250  *             types of key events are requested (#SPI_KEY_PRESSED, etc.).
251  * @sync_type: a #AccessibleKeyListenerSyncType parameter indicating
252  *             the behavior of the notification/listener transaction.
253  *             
254  * Register a listener for keystroke events, either pre-emptively for
255  *             all windows (SPI_KEYLISTENER_ALL_WINDOWS), or
256  *             non-preemptively (SPI_KEYLISTENER_NOSYNC).
257  *             ( Other sync_type values may be available in the future.)
258  **/
259 void
260 registerAccessibleKeystrokeListener (AccessibleKeystrokeListener *listener,
261                                      AccessibleKeySet *keys,
262                                      AccessibleKeyMaskType modmask,
263                                      AccessibleKeyEventMask eventmask,
264                                      AccessibleKeyListenerSyncType sync_type)
265 {
266   Accessibility_ControllerEventMask *controller_event_mask =
267           Accessibility_ControllerEventMask__alloc();
268   Accessibility_DeviceEventController device_event_controller = 
269           Accessibility_Registry_getDeviceEventController (spi_registry (), spi_ev ());
270   Accessibility_KeySet *key_set = Accessibility_KeySet__alloc();
271   Accessibility_KeyEventTypeSeq *key_events = Accessibility_KeyEventTypeSeq__alloc();
272   Accessibility_KeystrokeListener spi_listener_corba_ref;
273   gint i, mask;
274   Accessibility_DeviceEventController_ref (device_event_controller, spi_ev ());
275
276   /* copy the keyval filter values from the C api into the CORBA KeySet */
277   if (keys)
278     {
279       key_set->_buffer = Accessibility_KeySet_allocbuf (
280                                                     (unsigned long) keys->len);
281       key_set->_length = (unsigned long) keys->len;
282       for (i=0; i < key_set->_length; ++i)
283         {
284           /* we overload the keyset long w/keycodes, the - bit acts as a flag */
285           key_set->_buffer[i] = (keys->keysyms[i]) ? keys->keysyms[i] :
286                                                  -keys->keycodes[i];
287           /* g_print ("key-set %d = %d\n", i, (int) key_set->_buffer[i]); */
288         }
289     }
290   /* copy the event filter values from the C api into the CORBA KeyEventTypeSeq */
291   mask=1;
292   i=0;
293   do
294     {
295       if (mask & eventmask) ++i; 
296       mask <<= 1;
297     } while (mask & 0xFFFF);
298   
299   key_events->_buffer = Accessibility_KeyEventTypeSeq_allocbuf (i);
300   i=0;
301   if (eventmask & SPI_KEY_PRESSED)
302     {
303       key_events->_buffer[i++] = Accessibility_KEY_PRESSED;
304     }
305   if (eventmask & SPI_KEY_RELEASED)
306     {
307       key_events->_buffer[i++] = Accessibility_KEY_RELEASED;
308     }
309   key_events->_length = i;
310   
311   controller_event_mask->value = (CORBA_unsigned_long) modmask;
312   controller_event_mask->refcount = (CORBA_unsigned_short) 1;
313
314   spi_listener_corba_ref = (Accessibility_KeystrokeListener)
315           CORBA_Object_duplicate (bonobo_object_corba_objref (bonobo_object (listener)), spi_ev ());
316   
317           Accessibility_DeviceEventController_registerKeystrokeListener (
318           device_event_controller,
319           spi_listener_corba_ref,
320           key_set,
321           controller_event_mask,
322           key_events,
323           (CORBA_boolean) ((sync_type & SPI_KEYLISTENER_ALL_WINDOWS)!=0),
324           spi_ev ());
325 }
326
327 /**
328  * deregisterAccessibleKeystrokeListener:
329  * @listener: a pointer to the #AccessibleKeystrokeListener for which
330  *            keystroke events are requested.
331  * @modmask:  the key modifier mask for which this listener is to be
332  *            'deregistered' (of type #AccessibleeyMaskType).
333  *
334  * Removes a keystroke event listener from the registry's listener queue,
335  *            ceasing notification of events with modifiers matching @modmask.
336  **/
337 void
338 deregisterAccessibleKeystrokeListener (AccessibleKeystrokeListener *listener,
339                                        AccessibleKeyMaskType modmask)
340 {
341   Accessibility_ControllerEventMask *controller_event_mask =
342           Accessibility_ControllerEventMask__alloc();
343   Accessibility_DeviceEventController device_event_controller = 
344           Accessibility_Registry_getDeviceEventController (spi_registry (), spi_ev ());
345   Accessibility_KeySet *all_keys = Accessibility_KeySet__alloc();
346   Accessibility_KeyEventTypeSeq *key_events = Accessibility_KeyEventTypeSeq__alloc();
347   Accessibility_KeystrokeListener spi_listener_corba_ref;
348   Accessibility_DeviceEventController_unref (device_event_controller, spi_ev ());
349   controller_event_mask->value = (CORBA_unsigned_long) modmask;
350   controller_event_mask->refcount = (CORBA_unsigned_short) 1;
351
352   spi_listener_corba_ref = (Accessibility_KeystrokeListener)
353           CORBA_Object_duplicate (bonobo_object_corba_objref (bonobo_object (listener)), spi_ev ());
354   
355   Accessibility_DeviceEventController_deregisterKeystrokeListener (
356           device_event_controller,
357           spi_listener_corba_ref,
358           all_keys,
359           controller_event_mask,
360           key_events,
361           (CORBA_boolean) TRUE,
362           spi_ev ());
363 }
364
365 /**
366  * generateKeyEvent:
367  * @keyval: a long integer indicating the keycode or keysym of the key event
368  *           being synthesized.
369  * @synth_type: a #AccessibleKeySynthType flag indicating whether @keyval
370  *           is to be interpreted as a keysym rather than a keycode
371  *           (SPI_KEYSYM), or whether to synthesize
372  *           SPI_KEY_PRESS, SPI_KEY_RELEASE, or both (SPI_KEY_PRESSRELEASE).
373  *
374  * Synthesize a keyboard event (as if a hardware keyboard event occurred in the
375  * current UI context).
376  *
377  **/
378 void
379 generateKeyEvent (long int keyval, AccessibleKeySynthType synth_type)
380 {
381 /* TODO: check current modifier status and
382  *  send keycode to alter, if necessary
383  */
384   Accessibility_DeviceEventController device_event_controller = 
385           Accessibility_Registry_getDeviceEventController (spi_registry (), spi_ev ());
386   Accessibility_DeviceEventController_generateKeyEvent (device_event_controller,
387                                                         keyval,
388                                                         (unsigned long) synth_type,
389                                                         spi_ev ());
390 }
391
392 /**
393  * generateMouseEvent:
394  * @x: a #long indicating the screen x coordinate of the mouse event.
395  * @y: a #long indicating the screen y coordinate of the mouse event.
396  * @name: a string indicating which mouse event to be synthesized
397  *        (e.g. "button1", "button2", "mousemove").
398  *
399  * Synthesize a mouse event at a specific screen coordinate.
400  * Most AT clients should use the #AccessibleAction interface when
401  * tempted to generate mouse events, rather than this method.
402  * Not Yet Implemented.
403  *
404  **/
405 void
406 generateMouseEvent (long x, long y, char *name)
407 {
408   ;
409 }
410