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