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