API revisions: tweaks to key event API, added some reserved slots for
[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 /* spi_registry.c: Global functions wrapping the registry */
24
25 #include <cspi/spi-private.h>
26
27 /**
28  * SPI_registerGlobalEventListener:
29  * @listener: the #AccessibleEventListener to be registered against an
30  *            event type.
31  * @eventType: a character string indicating the type of events for which
32  *            notification is requested.  Format is
33  *            EventClass:major_type:minor_type:detail
34  *            where all subfields other than EventClass are optional.
35  *            EventClasses include "object", "window", "mouse",
36  *            and toolkit events (e.g. "Gtk", "AWT").
37  *            Examples: "focus:", "Gtk:GtkWidget:button_press_event".
38  *
39  * Legal object event types:
40  *
41  *    (property change events)
42  *
43  *            object:property-change
44  *            object:property-change:accessible-name
45  *            object:property-change:accessible-state
46  *            object:property-change:accessible-description
47  *            object:property-change:accessible-parent
48  *            object:property-change:accessible-value
49  *            object:property-change:accessible-role
50  *            object:property-change:accessible-table-caption
51  *            object:property-change:accessible-table-column-description
52  *            object:property-change:accessible-table-column-header
53  *            object:property-change:accessible-table-row-description
54  *            object:property-change:accessible-table-row-header
55  *            object:property-change:accessible-table-summary
56  *
57  *    (other object events)
58  *
59  *            object:children-changed
60  *            object:visible-data-changed
61  *            object:selection-changed
62  *            object:text-selection-changed
63  *            object:text-changed
64  *            object:text-caret-moved
65  *            object:row-inserted
66  *            object:row-reordered
67  *            object:row-deleted
68  *            object:column-inserted
69  *            object:column-reordered
70  *            object:column-deleted
71  *            object:model-changed
72  *
73  *  (window events)
74  *
75  *            window:minimize
76  *            window:maximize
77  *            window:restore
78  *            window:close
79  *            window:create
80  *            window:reparent
81  *            window:desktop-create
82  *            window:desktop-destroy
83  *            window:focus-in
84  *            window:focus-out
85  *            window:raise
86  *            window:lower
87  *            window:move
88  *            window:resize
89  *            window:shade
90  *            window:unshade
91  *            window:restyle
92  *
93  * NOTE: this string may be UTF-8, but should not contain byte value 56
94  *            (ascii ':'), except as a delimiter, since non-UTF-8 string
95  *            delimiting functions are used internally.
96  *            In general, listening to
97  *            toolkit-specific events is not recommended.
98  *
99  * Add an in-process callback function to an existing AccessibleEventListener.
100  *
101  * Returns: #TRUE if successful, otherwise #FALSE.
102  **/
103 SPIBoolean
104 SPI_registerGlobalEventListener (AccessibleEventListener *listener,
105                                  const char              *eventType)
106 {
107   SPIBoolean retval;
108
109   if (!listener)
110     {
111       return FALSE;
112     }
113
114   Accessibility_Registry_registerGlobalEventListener (
115     cspi_registry (),
116     cspi_event_listener_get_corba (listener),
117     eventType, cspi_ev ());
118
119   retval = !cspi_exception ();
120  
121   return retval;
122 }
123
124 /**
125  * SPI_deregisterGlobalEventListenerAll:
126  * @listener: the #AccessibleEventListener to be registered against
127  *            an event type.
128  *
129  * deregisters an AccessibleEventListener from the registry, for all
130  *            event types it may be listening to. Use
131  *            AccessibleEventListener_unref to release the
132  *            listener reference.
133  *
134  * Returns: #TRUE if successful, otherwise #FALSE.
135  **/
136 SPIBoolean
137 SPI_deregisterGlobalEventListenerAll (AccessibleEventListener *listener)
138 {
139   if (!listener)
140     {
141       return FALSE;
142     }
143
144   Accessibility_Registry_deregisterGlobalEventListenerAll (
145     cspi_registry (),
146     cspi_event_listener_get_corba (listener),
147     cspi_ev ());
148
149   return !cspi_exception ();
150 }
151
152 /**
153  * SPI_deregisterGlobalEventListener:
154  * @listener: the #AccessibleEventListener registered against an event type.
155  * @eventType: a string specifying the event type for which this
156  *             listener is to be deregistered.
157  *
158  * deregisters an AccessibleEventListener from the registry, for a specific
159  *             event type.
160  *
161  * Returns: #TRUE if successful, otherwise #FALSE.
162  **/
163 SPIBoolean
164 SPI_deregisterGlobalEventListener (AccessibleEventListener *listener,
165                                    const char              *eventType)
166 {
167   if (!listener)
168     {
169       return FALSE;
170     }
171
172   Accessibility_Registry_deregisterGlobalEventListener (
173     cspi_registry (), 
174     cspi_event_listener_get_corba (listener),
175     (CORBA_char *) eventType, cspi_ev ());
176
177   return !cspi_exception ();
178 }
179
180 /**
181  * SPI_getDesktopCount:
182  *
183  * Get the number of virtual desktops.
184  * NOTE: currently multiple virtual desktops are not implemented, this
185  *       function always returns '1'.
186  *
187  * Returns: an integer indicating the number of active virtual desktops.
188  **/
189 int
190 SPI_getDesktopCount ()
191 {
192   int retval;
193
194   retval = Accessibility_Registry_getDesktopCount (
195     cspi_registry (), cspi_ev ());
196
197   cspi_return_val_if_ev ("getDesktopCount", -1);
198
199   return retval;
200 }
201
202 /**
203  * SPI_getDesktop:
204  * @i: an integer indicating which of the accessible desktops is to be returned.
205  *
206  * Get the virtual desktop indicated by index @i.
207  * NOTE: currently multiple virtual desktops are not implemented, this
208  *       function always returns '1'.
209  *
210  * Returns: a pointer to the 'i-th' virtual desktop's #Accessible representation.
211  **/
212 Accessible*
213 SPI_getDesktop (int i)
214 {
215   return cspi_object_add (
216     Accessibility_Registry_getDesktop (
217       cspi_registry (), (CORBA_short) i, cspi_ev ()));
218 }
219
220 /**
221  * SPI_getDesktopList:
222  * @list: a pointer to an array of #Accessible objects.
223  *
224  * Get the list of virtual desktops.  On return, @list will point
225  *     to a newly-created array of virtual desktop pointers.
226  *     It is the responsibility of the caller to free this array when
227  *     it is no longer needed.
228  *
229  * Not Yet Implemented : this implementation always returns a single
230  * #Accessible desktop.
231  *
232  * Returns: an integer indicating how many virtual desktops have been
233  *          placed in the list pointed to by parameter @list.
234  **/
235 int
236 SPI_getDesktopList (Accessible **list)
237 {
238   *list = NULL;
239   return 0;
240 }
241
242 /**
243  * SPI_registerAccessibleKeystrokeListener:
244  * @listener:  a pointer to the #AccessibleKeystrokeListener for which
245  *             keystroke events are requested.
246  * @keys:      a pointer to the #AccessibleKeySet indicating which
247  *             keystroke events are requested, or #CSPI_KEYSET_ALL_KEYS.
248  * @modmask:   an #AccessibleKeyMaskType mask indicating which
249  *             key event modifiers must be set in combination with @keys,
250  *             events will only be reported for key events for which all
251  *             modifiers in @modmask are set.  If you wish to listen for
252  *             events with multiple modifier combinations you must call
253  *             registerAccessibleKeystrokeListener() once for each combination.
254  * @eventmask: an #AccessibleKeyMaskType mask indicating which
255  *             types of key events are requested (#SPI_KEY_PRESSED, etc.).
256  * @sync_type: a #AccessibleKeyListenerSyncType parameter indicating
257  *             the behavior of the notification/listener transaction.
258  *             
259  * Register a listener for keystroke events, either pre-emptively for
260  *             all windows (CSPI_KEYLISTENER_ALL_WINDOWS), or
261  *             non-preemptively (CSPI_KEYLISTENER_NOSYNC).
262  *             ( Other sync_type values may be available in the future.)
263  *
264  * Returns: #TRUE if successful, otherwise #FALSE.
265  **/
266 SPIBoolean
267 SPI_registerAccessibleKeystrokeListener (AccessibleKeystrokeListener *listener,
268                                          AccessibleKeySet *keys,
269                                          AccessibleKeyMaskType modmask,
270                                          AccessibleKeyEventMask eventmask,
271                                          AccessibleKeyListenerSyncType sync_type)
272 {
273   gint                                i, mask;
274   Accessibility_KeySet                key_set;
275   Accessibility_KeyEventTypeSeq       key_events;
276   Accessibility_ControllerEventMask   controller_event_mask;
277   Accessibility_DeviceEventController device_event_controller;
278   Accessibility_EventListenerMode     listener_mode;
279
280   if (!listener)
281     {
282       return FALSE;
283     }
284
285   device_event_controller = 
286     Accessibility_Registry_getDeviceEventController (cspi_registry (), cspi_ev ());
287
288   cspi_return_val_if_ev ("getting event controller", FALSE);
289
290   /* copy the keyval filter values from the C api into the CORBA KeySet */
291   if (keys)
292     {
293       key_set._length = keys->len;
294       key_set._buffer = Accessibility_KeySet_allocbuf (keys->len);
295       for (i = 0; i < key_set._length; ++i)
296         {
297           /* we overload the keyset long w/keycodes, the - bit acts as a flag */
298           key_set._buffer[i] = (keys->keysyms[i]) ? keys->keysyms[i] :
299                                                   - keys->keycodes[i];
300           /* fprintf (stderr, "key-set %d = %d\n", i, (int) key_set->_buffer[i]); */
301         }
302     }
303   else
304     {
305       key_set._length = 0;
306       key_set._buffer = NULL;
307     }
308         
309   /* copy the event filter values from the C api into the CORBA KeyEventTypeSeq */
310   mask = 1;
311   i = 0;
312   do
313     {
314       if (mask & eventmask)
315         {
316           ++i; 
317         }
318       mask <<= 1;
319     }
320   while (mask & 0xFFFF);
321   
322   key_events._buffer = Accessibility_KeyEventTypeSeq_allocbuf (i);
323   i = 0;
324   if (eventmask & SPI_KEY_PRESSED)
325     {
326       key_events._buffer[i++] = Accessibility_KEY_PRESSED;
327     }
328   if (eventmask & SPI_KEY_RELEASED)
329     {
330       key_events._buffer[i++] = Accessibility_KEY_RELEASED;
331     }
332   key_events._length = i;
333   
334   controller_event_mask = (CORBA_unsigned_long) modmask;
335
336   listener_mode.synchronous =
337           (CORBA_boolean) ((sync_type & SPI_KEYLISTENER_SYNCHRONOUS)!=0);
338   listener_mode.preemptive =
339           (CORBA_boolean) ((sync_type & SPI_KEYLISTENER_CANCONSUME)!=0);
340   listener_mode.global =
341           (CORBA_boolean) ((sync_type & SPI_KEYLISTENER_ALL_WINDOWS)!=0);
342
343   Accessibility_DeviceEventController_registerKeystrokeListener (
344     device_event_controller,
345     cspi_event_listener_get_corba (listener),
346     &key_set,
347     controller_event_mask,
348     &key_events,
349     &listener_mode,
350     cspi_ev ());
351
352   cspi_return_val_if_ev ("registering keystroke listener", FALSE);
353
354   cspi_release_unref (device_event_controller);
355
356   return TRUE;
357 }
358
359 /**
360  * SPI_deregisterAccessibleKeystrokeListener:
361  * @listener: a pointer to the #AccessibleKeystrokeListener for which
362  *            keystroke events are requested.
363  * @modmask:  the key modifier mask for which this listener is to be
364  *            'deregistered' (of type #AccessibleeyMaskType).
365  *
366  * Removes a keystroke event listener from the registry's listener queue,
367  *            ceasing notification of events with modifiers matching @modmask.
368  *
369  * Returns: #TRUE if successful, otherwise #FALSE.
370  **/
371 SPIBoolean
372 SPI_deregisterAccessibleKeystrokeListener (AccessibleKeystrokeListener *listener,
373                                            AccessibleKeyMaskType modmask)
374 {
375   Accessibility_ControllerEventMask   controller_event_mask;
376   Accessibility_KeySet                key_set;
377   Accessibility_KeyEventTypeSeq       key_events;
378   Accessibility_DeviceEventController device_event_controller;
379
380   if (!listener)
381     {
382       return FALSE;
383     }
384
385   device_event_controller = 
386     Accessibility_Registry_getDeviceEventController (cspi_registry (), cspi_ev ());
387
388   cspi_return_val_if_ev ("getting keystroke listener", FALSE);
389
390   controller_event_mask = (CORBA_unsigned_long) modmask;
391
392   key_events._buffer = NULL;
393   key_events._length = 0;
394
395   key_set._buffer = NULL;
396   key_set._length = 0;
397
398   Accessibility_DeviceEventController_deregisterKeystrokeListener (
399     device_event_controller,
400     cspi_event_listener_get_corba (listener),
401     &key_set,
402     controller_event_mask,
403     &key_events,
404     cspi_ev ());
405
406   cspi_release_unref (device_event_controller);
407
408   return TRUE;
409 }
410
411 /**
412  * SPI_generateKeyboardEvent:
413  * @keyval: a long integer indicating the keycode or keysym of the key event
414  *           being synthesized.
415  * @synth_type: a #AccessibleKeySynthType flag indicating whether @keyval
416  *           is to be interpreted as a keysym rather than a keycode
417  *           (CSPI_KEYSYM), or whether to synthesize
418  *           SPI_KEY_PRESS, SPI_KEY_RELEASE, or both (SPI_KEY_PRESSRELEASE).
419  *
420  * Synthesize a keyboard event (as if a hardware keyboard event occurred in the
421  * current UI context).
422  *
423  * Returns: #TRUE if successful, otherwise #FALSE.
424  **/
425 SPIBoolean
426 SPI_generateKeyboardEvent (long int keyval,
427                            char *keystring,
428                            AccessibleKeySynthType synth_type)
429 {
430 /* TODO: check current modifier status and
431  *  send keycode to alter, if necessary
432  */
433         
434   /* TODO: implement keystring use case */
435   Accessibility_KeySynthType keysynth_type;
436   Accessibility_DeviceEventController device_event_controller = 
437           Accessibility_Registry_getDeviceEventController (cspi_registry (), cspi_ev ());
438
439   cspi_return_val_if_ev ("getting event controller for key event gen", FALSE);
440
441   switch (synth_type)
442     {
443       case SPI_KEY_PRESS:
444           keysynth_type = Accessibility_KEY_PRESS;
445           break;
446       case SPI_KEY_RELEASE:
447           keysynth_type = Accessibility_KEY_RELEASE;
448           break;
449       case SPI_KEY_PRESSRELEASE:
450           keysynth_type = Accessibility_KEY_PRESSRELEASE;
451           break;
452       case SPI_KEY_SYM:
453           keysynth_type = Accessibility_KEY_SYM;
454           break;
455       case SPI_KEY_STRING:
456           keysynth_type = Accessibility_KEY_STRING;
457           break;
458     }
459
460   Accessibility_DeviceEventController_generateKeyboardEvent (device_event_controller,
461                                                              keyval,
462                                                              "",
463                                                              keysynth_type,
464                                                              cspi_ev ());
465
466   cspi_return_val_if_ev ("generating keyboard event", FALSE);
467
468   cspi_release_unref (device_event_controller);
469
470   return TRUE;
471 }
472
473 /**
474  * SPI_generateMouseEvent:
475  * @x: a #long indicating the screen x coordinate of the mouse event.
476  * @y: a #long indicating the screen y coordinate of the mouse event.
477  * @name: a string indicating which mouse event to be synthesized
478  *        (e.g. "button1", "button2", "mousemove").
479  *
480  * Synthesize a mouse event at a specific screen coordinate.
481  * Most AT clients should use the #AccessibleAction interface when
482  * tempted to generate mouse events, rather than this method.
483  * Not Yet Implemented.
484  *
485  * Returns: #TRUE if successful, otherwise #FALSE.
486  **/
487 SPIBoolean
488 SPI_generateMouseEvent (long x, long y, char *name)
489 {
490   return FALSE;
491 }
492