Merged Michael's branch back into HEAD, and fixed a number of reference counting...
[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 boolean
95 registerGlobalEventListener (AccessibleEventListener *listener,
96                              char *eventType)
97 {
98   boolean retval;
99
100   Accessibility_Registry_registerGlobalEventListener (
101                          cspi_registry (),
102                          (Accessibility_EventListener)
103                             bonobo_object_corba_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 boolean
125 deregisterGlobalEventListenerAll (AccessibleEventListener *listener)
126 {
127   Accessibility_Registry_deregisterGlobalEventListenerAll (
128                          cspi_registry (),
129                          (Accessibility_EventListener)
130                             CORBA_Object_duplicate (
131                                     bonobo_object_corba_objref (
132                                             bonobo_object (listener)), cspi_ev ()),
133                          cspi_ev ());
134   if (!cspi_exception ())
135     {
136       bonobo_object_unref (BONOBO_OBJECT (listener));       
137       /* Would prefer that this were not a bonobo object: g_object_unref (listener);*/
138     }
139
140   return !cspi_exception ();
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           cspi_registry (),
160           (Accessibility_EventListener)
161           CORBA_Object_duplicate (
162                   bonobo_object_corba_objref (bonobo_object (listener)), cspi_ev ()),
163           (CORBA_char *) eventType,
164           cspi_ev ());
165
166   return !cspi_exception ();
167 }
168
169 /**
170  * getDesktopCount:
171  *
172  * Get the number of virtual desktops.
173  * NOTE: currently multiple virtual desktops are not implemented, this
174  *       function always returns '1'.
175  *
176  * Returns: an integer indicating the number of active virtual desktops.
177  *
178  **/
179 int
180 getDesktopCount ()
181 {
182   return Accessibility_Registry_getDesktopCount (cspi_registry (), cspi_ev ());
183 }
184
185 /**
186  * getDesktop:
187  * @i: an integer indicating which of the accessible desktops is to be returned.
188  *
189  * Get the virtual desktop indicated by index @i.
190  * NOTE: currently multiple virtual desktops are not implemented, this
191  *       function always returns '1'.
192  *
193  * Returns: a pointer to the 'i-th' virtual desktop's #Accessible representation.
194  *
195  **/
196 Accessible*
197 getDesktop (int i)
198 {
199   return cspi_object_add (Accessibility_Registry_getDesktop (cspi_registry (),
200                                                              (CORBA_short) i,
201                                                              cspi_ev ()));
202 }
203
204 /**
205  * getDesktopList:
206  * @list: a pointer to an array of #Accessible objects.
207  *
208  * Get the list of virtual desktops.  On return, @list will point
209  *     to a newly-created array of virtual desktop pointers.
210  *     It is the responsibility of the caller to free this array when
211  *     it is no longer needed.
212  *
213  * Not Yet Implemented : this implementation always returns a single
214  * #Accessible desktop.
215  *
216  * Returns: an integer indicating how many virtual desktops have been
217  *          placed in the list pointed to by parameter @list.
218  **/
219 int
220 getDesktopList (Accessible **list)
221 {
222   *list = NULL;
223   return 0;
224 }
225
226 #if 0
227 static gboolean
228 key_event_source_func (void *p)
229 {
230   GList *listeners = (GList *)p;
231   XEvent *x_event = g_new0 (XEvent, 1);
232   while (XPending (display))
233     {
234       XNextEvent (display, x_event);
235       while (listeners)
236         {
237         /* if the listener mask matches, notify it*/
238           if (1)
239             {
240               ;   
241             }
242         }
243     }
244   return TRUE;
245 }
246 #endif
247
248 /**
249  * registerAccessibleKeystrokeListener:
250  * @listener:  a pointer to the #AccessibleKeystrokeListener for which
251  *             keystroke events are requested.
252  * @keys:      a pointer to the #AccessibleKeySet indicating which
253  *             keystroke events are requested, or #CSPI_KEYSET_ALL_KEYS.
254  * @modmask:   an #AccessibleKeyMaskType mask indicating which
255  *             key event modifiers must be set in combination with @keys,
256  *             events will only be reported for key events for which all
257  *             modifiers in @modmask are set.  If you wish to listen for
258  *             events with multiple modifier combinations you must call
259  *             registerAccessibleKeystrokeListener() once for each combination.
260  * @eventmask: an #AccessibleKeyMaskType mask indicating which
261  *             types of key events are requested (#SPI_KEY_PRESSED, etc.).
262  * @sync_type: a #AccessibleKeyListenerSyncType parameter indicating
263  *             the behavior of the notification/listener transaction.
264  *             
265  * Register a listener for keystroke events, either pre-emptively for
266  *             all windows (CSPI_KEYLISTENER_ALL_WINDOWS), or
267  *             non-preemptively (CSPI_KEYLISTENER_NOSYNC).
268  *             ( Other sync_type values may be available in the future.)
269  **/
270 void
271 registerAccessibleKeystrokeListener (AccessibleKeystrokeListener *listener,
272                                      AccessibleKeySet *keys,
273                                      AccessibleKeyMaskType modmask,
274                                      AccessibleKeyEventMask eventmask,
275                                      AccessibleKeyListenerSyncType sync_type)
276 {
277   Accessibility_ControllerEventMask *controller_event_mask =
278           Accessibility_ControllerEventMask__alloc();
279   Accessibility_DeviceEventController device_event_controller = 
280           Accessibility_Registry_getDeviceEventController (cspi_registry (), cspi_ev ());
281   Accessibility_KeySet *key_set = Accessibility_KeySet__alloc();
282   Accessibility_KeyEventTypeSeq *key_events = Accessibility_KeyEventTypeSeq__alloc();
283   Accessibility_KeystrokeListener cspi_listener_corba_ref;
284   gint i, mask;
285   Accessibility_DeviceEventController_ref (device_event_controller, cspi_ev ());
286
287   /* copy the keyval filter values from the C api into the CORBA KeySet */
288   if (keys)
289     {
290       key_set->_buffer = Accessibility_KeySet_allocbuf (
291                                                     (unsigned long) keys->len);
292       key_set->_length = (unsigned long) keys->len;
293       for (i=0; i < key_set->_length; ++i)
294         {
295           /* we overload the keyset long w/keycodes, the - bit acts as a flag */
296           key_set->_buffer[i] = (keys->keysyms[i]) ? keys->keysyms[i] :
297                                                  -keys->keycodes[i];
298           /* g_print ("key-set %d = %d\n", i, (int) key_set->_buffer[i]); */
299         }
300     }
301   /* copy the event filter values from the C api into the CORBA KeyEventTypeSeq */
302   mask=1;
303   i=0;
304   do
305     {
306       if (mask & eventmask) ++i; 
307       mask <<= 1;
308     } while (mask & 0xFFFF);
309   
310   key_events->_buffer = Accessibility_KeyEventTypeSeq_allocbuf (i);
311   i=0;
312   if (eventmask & SPI_KEY_PRESSED)
313     {
314       key_events->_buffer[i++] = Accessibility_KEY_PRESSED;
315     }
316   if (eventmask & SPI_KEY_RELEASED)
317     {
318       key_events->_buffer[i++] = Accessibility_KEY_RELEASED;
319     }
320   key_events->_length = i;
321   
322   controller_event_mask->value = (CORBA_unsigned_long) modmask;
323   controller_event_mask->refcount = (CORBA_unsigned_short) 1;
324
325   cspi_listener_corba_ref = (Accessibility_KeystrokeListener)
326           CORBA_Object_duplicate (bonobo_object_corba_objref (bonobo_object (listener)), cspi_ev ());
327   
328           Accessibility_DeviceEventController_registerKeystrokeListener (
329           device_event_controller,
330           cspi_listener_corba_ref,
331           key_set,
332           controller_event_mask,
333           key_events,
334           (CORBA_boolean) ((sync_type & SPI_KEYLISTENER_ALL_WINDOWS)!=0),
335           cspi_ev ());
336 }
337
338 /**
339  * deregisterAccessibleKeystrokeListener:
340  * @listener: a pointer to the #AccessibleKeystrokeListener for which
341  *            keystroke events are requested.
342  * @modmask:  the key modifier mask for which this listener is to be
343  *            'deregistered' (of type #AccessibleeyMaskType).
344  *
345  * Removes a keystroke event listener from the registry's listener queue,
346  *            ceasing notification of events with modifiers matching @modmask.
347  **/
348 void
349 deregisterAccessibleKeystrokeListener (AccessibleKeystrokeListener *listener,
350                                        AccessibleKeyMaskType modmask)
351 {
352   Accessibility_ControllerEventMask *controller_event_mask =
353           Accessibility_ControllerEventMask__alloc();
354   Accessibility_DeviceEventController device_event_controller = 
355           Accessibility_Registry_getDeviceEventController (cspi_registry (), cspi_ev ());
356   Accessibility_KeySet *all_keys = Accessibility_KeySet__alloc();
357   Accessibility_KeyEventTypeSeq *key_events = Accessibility_KeyEventTypeSeq__alloc();
358   Accessibility_KeystrokeListener cspi_listener_corba_ref;
359   Accessibility_DeviceEventController_unref (device_event_controller, cspi_ev ());
360   controller_event_mask->value = (CORBA_unsigned_long) modmask;
361   controller_event_mask->refcount = (CORBA_unsigned_short) 1;
362
363   cspi_listener_corba_ref = (Accessibility_KeystrokeListener)
364           CORBA_Object_duplicate (BONOBO_OBJREF(listener), cspi_ev ());
365   
366   Accessibility_DeviceEventController_deregisterKeystrokeListener (
367           device_event_controller,
368           cspi_listener_corba_ref,
369           all_keys,
370           controller_event_mask,
371           key_events,
372           (CORBA_boolean) TRUE,
373           cspi_ev ());
374 }
375
376 /**
377  * generateKeyEvent:
378  * @keyval: a long integer indicating the keycode or keysym of the key event
379  *           being synthesized.
380  * @synth_type: a #AccessibleKeySynthType flag indicating whether @keyval
381  *           is to be interpreted as a keysym rather than a keycode
382  *           (CSPI_KEYSYM), or whether to synthesize
383  *           SPI_KEY_PRESS, SPI_KEY_RELEASE, or both (SPI_KEY_PRESSRELEASE).
384  *
385  * Synthesize a keyboard event (as if a hardware keyboard event occurred in the
386  * current UI context).
387  *
388  **/
389 void
390 generateKeyEvent (long int keyval, AccessibleKeySynthType synth_type)
391 {
392 /* TODO: check current modifier status and
393  *  send keycode to alter, if necessary
394  */
395   Accessibility_DeviceEventController device_event_controller = 
396           Accessibility_Registry_getDeviceEventController (cspi_registry (), cspi_ev ());
397   Accessibility_DeviceEventController_generateKeyEvent (device_event_controller,
398                                                         keyval,
399                                                         (unsigned long) synth_type,
400                                                         cspi_ev ());
401 }
402
403 /**
404  * generateMouseEvent:
405  * @x: a #long indicating the screen x coordinate of the mouse event.
406  * @y: a #long indicating the screen y coordinate of the mouse event.
407  * @name: a string indicating which mouse event to be synthesized
408  *        (e.g. "button1", "button2", "mousemove").
409  *
410  * Synthesize a mouse event at a specific screen coordinate.
411  * Most AT clients should use the #AccessibleAction interface when
412  * tempted to generate mouse events, rather than this method.
413  * Not Yet Implemented.
414  *
415  **/
416 void
417 generateMouseEvent (long x, long y, char *name)
418 {
419   ;
420 }
421