d567d34a5b679f317f9f2eb990fd80449a283143
[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-description
46  *            object:property-change:accessible-parent
47  *            object:property-change:accessible-value
48  *            object:property-change:accessible-role
49  *            object:property-change:accessible-table-caption
50  *            object:property-change:accessible-table-column-description
51  *            object:property-change:accessible-table-column-header
52  *            object:property-change:accessible-table-row-description
53  *            object:property-change:accessible-table-row-header
54  *            object:property-change:accessible-table-summary
55  *
56  *    (other object events)
57  *
58  *            object:state-changed 
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:activate
84  *            window:deactivate
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   if (!listener)
108     {
109       return FALSE;
110     }
111
112   Accessibility_Registry_registerGlobalEventListener (
113     cspi_registry (),
114     cspi_event_listener_get_corba (listener),
115     eventType, cspi_ev ());
116
117   return  !cspi_exception ();
118 }
119
120 /**
121  * SPI_deregisterGlobalEventListenerAll:
122  * @listener: the #AccessibleEventListener to be registered against
123  *            an event type.
124  *
125  * deregisters an AccessibleEventListener from the registry, for all
126  *            event types it may be listening to. Use
127  *            AccessibleEventListener_unref to release the
128  *            listener reference.
129  *
130  * Returns: #TRUE if successful, otherwise #FALSE.
131  **/
132 SPIBoolean
133 SPI_deregisterGlobalEventListenerAll (AccessibleEventListener *listener)
134 {
135   if (!listener)
136     {
137       return FALSE;
138     }
139
140   Accessibility_Registry_deregisterGlobalEventListenerAll (
141     cspi_registry (),
142     cspi_event_listener_get_corba (listener),
143     cspi_ev ());
144
145   return !cspi_exception ();
146 }
147
148 /**
149  * SPI_deregisterGlobalEventListener:
150  * @listener: the #AccessibleEventListener registered against an event type.
151  * @eventType: a string specifying the event type for which this
152  *             listener is to be deregistered.
153  *
154  * deregisters an AccessibleEventListener from the registry, for a specific
155  *             event type.
156  *
157  * Returns: #TRUE if successful, otherwise #FALSE.
158  **/
159 SPIBoolean
160 SPI_deregisterGlobalEventListener (AccessibleEventListener *listener,
161                                    const char              *eventType)
162 {
163   if (!listener)
164     {
165       return FALSE;
166     }
167
168   Accessibility_Registry_deregisterGlobalEventListener (
169     cspi_registry (), 
170     cspi_event_listener_get_corba (listener),
171     eventType, cspi_ev ());
172
173   return !cspi_exception ();
174 }
175
176 /**
177  * SPI_getDesktopCount:
178  *
179  * Get the number of virtual desktops.
180  * NOTE: currently multiple virtual desktops are not implemented, this
181  *       function always returns '1'.
182  *
183  * Returns: an integer indicating the number of active virtual desktops.
184  **/
185 int
186 SPI_getDesktopCount ()
187 {
188   int retval;
189
190   retval = Accessibility_Registry_getDesktopCount (
191     cspi_registry (), cspi_ev ());
192
193   cspi_return_val_if_ev ("getDesktopCount", -1);
194
195   return retval;
196 }
197
198 /**
199  * SPI_getDesktop:
200  * @i: an integer indicating which of the accessible desktops is to be returned.
201  *
202  * Get the virtual desktop indicated by index @i.
203  * NOTE: currently multiple virtual desktops are not implemented, this
204  *       function always returns '1'.
205  *
206  * Returns: a pointer to the 'i-th' virtual desktop's #Accessible representation.
207  **/
208 Accessible*
209 SPI_getDesktop (int i)
210 {
211   return cspi_object_add (
212     Accessibility_Registry_getDesktop (
213       cspi_registry (), i, cspi_ev ()));
214 }
215
216 /**
217  * SPI_getDesktopList:
218  * @desktop_list: a pointer to an array of #Accessible references.
219  *
220  * Get the list of virtual desktops.  On return, @list will point
221  *     to a newly-created, NULL terminated array of virtual desktop
222  *     pointers.
223  *     It is the responsibility of the caller to free this array when
224  *     it is no longer needed.
225  *
226  * Not Yet Implemented : this implementation always returns a single
227  * #Accessible desktop.
228  *
229  * Returns: an integer indicating how many virtual desktops have been
230  *          placed in the list pointed to by parameter @list.
231  **/
232 int
233 SPI_getDesktopList (Accessible ***desktop_list)
234 {
235   int i;
236   Accessible **list;
237   Accessibility_DesktopSeq *desktops;
238
239   if (!desktop_list)
240           return 0;
241
242   *desktop_list = NULL;
243
244   desktops = Accessibility_Registry_getDesktopList (cspi_registry (),
245                                                     cspi_ev ());
246
247   cspi_return_val_if_ev ("getDesktopList", 0);
248
249   list = g_new0 (Accessible *, desktops->_length + 1);
250
251   for (i = 0; i < desktops->_length; i++)
252     {
253       list [i] = cspi_object_add (
254               CORBA_Object_duplicate (desktops->_buffer [i], cspi_ev ()));
255     }
256   list [i] = NULL;
257
258   CORBA_free (desktops);
259
260   *desktop_list = list;
261
262   return i;
263 }
264
265 /**
266  * SPI_freeDesktopList:
267  * @desktop_list: a pointer to an array of #Accessible objects
268  * as returned from @SPI_getDesktopList
269  * 
270  * This routine frees the memory associated with the list.
271  **/
272 void
273 SPI_freeDesktopList (Accessible **desktop_list)
274 {
275   Accessible **p;
276   
277   for (p = desktop_list; p && *p; p++)
278     {
279       cspi_object_unref (*p);
280     }
281   g_free (desktop_list);
282 }
283
284 /**
285  * SPI_KEYSET_ALL_KEYS:
286  * @SPI_KEYSET_ALL_KEYS: A special value for an AccessibleKeySet type, which tacitly
287  *                       includes all keycodes and keyvals for the specified modifier set.
288  **/
289
290 /**
291  * SPI_registerAccessibleKeystrokeListener:
292  * @listener:  a pointer to the #AccessibleKeystrokeListener for which
293  *             keystroke events are requested.
294  * @keys:      a pointer to the #AccessibleKeySet indicating which
295  *             keystroke events are requested, or #CSPI_KEYSET_ALL_KEYS.
296  * @modmask:   an #AccessibleKeyMaskType mask indicating which
297  *             key event modifiers must be set in combination with @keys,
298  *             events will only be reported for key events for which all
299  *             modifiers in @modmask are set.  If you wish to listen for
300  *             events with multiple modifier combinations you must call
301  *             registerAccessibleKeystrokeListener() once for each combination.
302  * @eventmask: an #AccessibleKeyMaskType mask indicating which
303  *             types of key events are requested (#SPI_KEY_PRESSED, etc.).
304  * @sync_type: a #AccessibleKeyListenerSyncType parameter indicating
305  *             the behavior of the notification/listener transaction.
306  *             
307  * Register a listener for keystroke events, either pre-emptively for
308  *             all windows (CSPI_KEYLISTENER_ALL_WINDOWS), or
309  *             non-preemptively (CSPI_KEYLISTENER_NOSYNC).
310  *             ( Other sync_type values may be available in the future.)
311  *
312  * Returns: #TRUE if successful, otherwise #FALSE.
313  **/
314 SPIBoolean
315 SPI_registerAccessibleKeystrokeListener (AccessibleKeystrokeListener  *listener,
316                                          AccessibleKeySet             *keys,
317                                          AccessibleKeyMaskType         modmask,
318                                          AccessibleKeyEventMask        eventmask,
319                                          AccessibleKeyListenerSyncType sync_type)
320 {
321   gint                                i, mask;
322   Accessibility_KeySet                key_set;
323   Accessibility_KeyEventTypeSeq       key_events;
324   Accessibility_ControllerEventMask   controller_event_mask;
325   Accessibility_DeviceEventController device_event_controller;
326   Accessibility_EventListenerMode     listener_mode;
327
328   if (!listener)
329     {
330       return FALSE;
331     }
332
333   device_event_controller = 
334     Accessibility_Registry_getDeviceEventController (cspi_registry (), cspi_ev ());
335
336   cspi_return_val_if_ev ("getting event controller", FALSE);
337
338   /* copy the keyval filter values from the C api into the CORBA KeySet */
339   if (keys)
340     {
341       key_set._length = keys->len;
342       key_set._buffer = Accessibility_KeySet_allocbuf (keys->len);
343       for (i = 0; i < key_set._length; ++i)
344         {
345           key_set._buffer[i].keycode = keys->keycodes[i];
346           key_set._buffer[i].keysym = keys->keysyms[i];
347           if (keys->keystrings && keys->keystrings[i]) 
348             {
349               key_set._buffer[i].keystring = keys->keystrings[i];
350             } 
351           else 
352             {
353               key_set._buffer[i].keystring = CORBA_string_dup("");
354             }
355         }
356     }
357   else
358     {
359       key_set._length = 0;
360       key_set._buffer = NULL;
361     }
362         
363   /* copy the event filter values from the C api into the CORBA KeyEventTypeSeq */
364   mask = 1;
365   i = 0;
366   do
367     {
368       if (mask & eventmask)
369         {
370           ++i; 
371         }
372       mask <<= 1;
373     }
374   while (mask & 0xFFFF);
375   
376   key_events._buffer = Accessibility_KeyEventTypeSeq_allocbuf (i);
377   i = 0;
378   if (eventmask & SPI_KEY_PRESSED)
379     {
380       key_events._buffer[i++] = Accessibility_KEY_PRESSED;
381     }
382   if (eventmask & SPI_KEY_RELEASED)
383     {
384       key_events._buffer[i++] = Accessibility_KEY_RELEASED;
385     }
386   key_events._length = i;
387   
388   controller_event_mask = (CORBA_unsigned_long) modmask;
389
390   listener_mode.synchronous =
391           (CORBA_boolean) ((sync_type & SPI_KEYLISTENER_SYNCHRONOUS)!=0);
392   listener_mode.preemptive =
393           (CORBA_boolean) ((sync_type & SPI_KEYLISTENER_CANCONSUME)!=0);
394   listener_mode.global =
395           (CORBA_boolean) ((sync_type & SPI_KEYLISTENER_ALL_WINDOWS)!=0);
396
397   Accessibility_DeviceEventController_registerKeystrokeListener (
398     device_event_controller,
399     cspi_event_listener_get_corba (listener),
400     &key_set,
401     controller_event_mask,
402     &key_events,
403     &listener_mode,
404     cspi_ev ());
405
406   cspi_return_val_if_ev ("registering keystroke listener", FALSE);
407
408   cspi_release_unref (device_event_controller);
409
410   return TRUE;
411 }
412
413 /**
414  * SPI_deregisterAccessibleKeystrokeListener:
415  * @listener: a pointer to the #AccessibleKeystrokeListener for which
416  *            keystroke events are requested.
417  * @modmask:  the key modifier mask for which this listener is to be
418  *            'deregistered' (of type #AccessibleeyMaskType).
419  *
420  * Removes a keystroke event listener from the registry's listener queue,
421  *            ceasing notification of events with modifiers matching @modmask.
422  *
423  * Returns: #TRUE if successful, otherwise #FALSE.
424  **/
425 SPIBoolean
426 SPI_deregisterAccessibleKeystrokeListener (AccessibleKeystrokeListener *listener,
427                                            AccessibleKeyMaskType        modmask)
428 {
429   Accessibility_ControllerEventMask   controller_event_mask;
430   Accessibility_KeySet                key_set;
431   Accessibility_KeyEventTypeSeq       key_events;
432   Accessibility_DeviceEventController device_event_controller;
433
434   if (!listener)
435     {
436       return FALSE;
437     }
438
439   device_event_controller = 
440     Accessibility_Registry_getDeviceEventController (cspi_registry (), cspi_ev ());
441
442   cspi_return_val_if_ev ("getting keystroke listener", FALSE);
443
444   controller_event_mask = (CORBA_unsigned_long) modmask;
445
446   key_events._buffer = NULL;
447   key_events._length = 0;
448
449   key_set._buffer = NULL;
450   key_set._length = 0;
451
452   Accessibility_DeviceEventController_deregisterKeystrokeListener (
453     device_event_controller,
454     cspi_event_listener_get_corba (listener),
455     &key_set,
456     controller_event_mask,
457     &key_events,
458     cspi_ev ());
459
460   cspi_release_unref (device_event_controller);
461
462   return TRUE;
463 }
464
465 /**
466  * SPI_generateKeyboardEvent:
467  * @keyval: a long integer indicating the keycode or keysym of the key event
468  *           being synthesized.
469  * @keystring: an (optional) UTF-8 string which, if @keyval is NULL,
470  *           indicates a 'composed' keyboard input string which is 
471  *           being synthesized; this type of keyboard event synthesis does
472  *           not emulate hardware keypresses but injects the string 
473  *           as though a composing input method (such as XIM) were used.
474  * @synth_type: a #AccessibleKeySynthType flag indicating whether @keyval
475  *           is to be interpreted as a keysym rather than a keycode
476  *           (CSPI_KEYSYM), or whether to synthesize
477  *           SPI_KEY_PRESS, SPI_KEY_RELEASE, or both (SPI_KEY_PRESSRELEASE).
478  *
479  * Synthesize a keyboard event (as if a hardware keyboard event occurred in the
480  * current UI context).
481  *
482  * Returns: #TRUE if successful, otherwise #FALSE.
483  **/
484 SPIBoolean
485 SPI_generateKeyboardEvent (long int keyval,
486                            char *keystring,
487                            AccessibleKeySynthType synth_type)
488 {
489 /* TODO: check current modifier status and
490  *  send keycode to alter, if necessary
491  */
492         
493   /* TODO: implement keystring use case */
494   Accessibility_KeySynthType keysynth_type;
495   Accessibility_DeviceEventController device_event_controller = 
496           Accessibility_Registry_getDeviceEventController (cspi_registry (), cspi_ev ());
497
498   cspi_return_val_if_ev ("getting event controller for key event gen", FALSE);
499
500   switch (synth_type)
501     {
502       case SPI_KEY_PRESS:
503           keysynth_type = Accessibility_KEY_PRESS;
504           break;
505       case SPI_KEY_RELEASE:
506           keysynth_type = Accessibility_KEY_RELEASE;
507           break;
508       case SPI_KEY_PRESSRELEASE:
509           keysynth_type = Accessibility_KEY_PRESSRELEASE;
510           break;
511       case SPI_KEY_SYM:
512           keysynth_type = Accessibility_KEY_SYM;
513           break;
514       case SPI_KEY_STRING:
515           keysynth_type = Accessibility_KEY_STRING;
516           break;
517       default:
518           return FALSE;
519     }
520
521   Accessibility_DeviceEventController_generateKeyboardEvent (device_event_controller,
522                                                              keyval,
523                                                              "",
524                                                              keysynth_type,
525                                                              cspi_ev ());
526
527   cspi_return_val_if_ev ("generating keyboard event", FALSE);
528
529   cspi_release_unref (device_event_controller);
530
531   return TRUE;
532 }
533
534 /**
535  * SPI_generateMouseEvent:
536  * @x: a #long indicating the screen x coordinate of the mouse event.
537  * @y: a #long indicating the screen y coordinate of the mouse event.
538  * @name: a string indicating which mouse event to be synthesized
539  *        (e.g. "b1p", "b1c", "b2r", "rel", "abs").
540  *
541  * Synthesize a mouse event at a specific screen coordinate.
542  * Most AT clients should use the #AccessibleAction interface when
543  * tempted to generate mouse events, rather than this method.
544  * Event names: b1p = button 1 press; b2r = button 2 release;
545  *              b3c = button 3 click; b2d = button 2 double-click;
546  *              abs = absolute motion; rel = relative motion.
547  *
548  * Returns: #TRUE if successful, otherwise #FALSE.
549  **/
550 SPIBoolean
551 SPI_generateMouseEvent (long x, long y, char *name)
552 {
553   Accessibility_DeviceEventController device_event_controller = 
554           Accessibility_Registry_getDeviceEventController (cspi_registry (), cspi_ev ());
555
556   cspi_return_val_if_ev ("getting event controller for mouse event gen", FALSE);
557
558   Accessibility_DeviceEventController_generateMouseEvent (device_event_controller,
559                                                           x, y, name, cspi_ev ());
560   cspi_return_val_if_ev ("generating mouse event", FALSE);
561
562   cspi_release_unref (device_event_controller);
563
564   return TRUE;
565 }
566