3 * AT-SPI - Assistive Technology Service Provider Interface
4 * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
6 * Copyright 2001, 2002 Sun Microsystems Inc.,
7 * Copyright 2001, 2002 Ximian, Inc.
9 * This library is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU Library General Public
11 * License as published by the Free Software Foundation; either
12 * version 2 of the License, or (at your option) any later version.
14 * This library is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
17 * Library General Public License for more details.
19 * You should have received a copy of the GNU Library General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
22 * Boston, MA 02111-1307, USA.
25 /* atspi_registry.c: Global functions wrapping the registry */
27 #include "atspi-private.h"
31 AtspiDeviceListener *listener;
33 AtspiKeyMaskType modmask;
34 AtspiKeyEventMask event_types;
36 } DeviceListenerEntry;
38 static GList *device_listeners;
41 * atspi_get_desktop_count:
43 * Gets the number of virtual desktops.
44 * NOTE: multiple virtual desktops are not implemented yet; as a
45 * consequence, this function always returns 1.
47 * Returns: a #gint indicating the number of active virtual desktops.
50 atspi_get_desktop_count ()
57 * @i: a #gint indicating which of the accessible desktops is to be returned.
59 * Gets the virtual desktop indicated by index @i.
60 * NOTE: currently multiple virtual desktops are not implemented;
61 * as a consequence, any @i value different from 0 will not return a
62 * virtual desktop - instead it will return NULL.
64 * Returns: (transfer full): a pointer to the @i-th virtual desktop's
65 * #AtspiAccessible representation.
68 atspi_get_desktop (gint i)
70 if (i != 0) return NULL;
71 return _atspi_ref_accessible (atspi_bus_registry, atspi_path_root);
75 * atspi_get_desktop_list:
77 * Gets the list of virtual desktops. On return, @list will point
78 * to a newly-created, NULL terminated array of virtual desktop
80 * It is the responsibility of the caller to free this array when
81 * it is no longer needed.
82 * NOTE: currently multiple virtual desktops are not implemented;
83 * this implementation always returns a #Garray with a single
84 * #AtspiAccessible desktop.
86 * Returns: (transfer full): a #GArray of desktops.
89 atspi_get_desktop_list ()
91 GArray *array = g_array_new (TRUE, TRUE, sizeof (AtspiAccessible *));
92 AtspiAccessible *desktop;
94 desktop = _atspi_ref_accessible (atspi_bus_registry, atspi_path_root);
96 g_array_index (array, AtspiAccessible *, 0) = desktop;
101 notify_keystroke_listener (DeviceListenerEntry *e)
103 gchar *path = _atspi_device_listener_get_path (e->listener);
105 dbus_uint32_t d_modmask = e->modmask;
106 dbus_uint32_t d_event_types = e->event_types;
107 AtspiEventListenerMode listener_mode;
108 gboolean retval = FALSE;
111 listener_mode.synchronous =
112 (dbus_bool_t) ((e->sync_type & ATSPI_KEYLISTENER_SYNCHRONOUS)!=0);
113 listener_mode.preemptive =
114 (dbus_bool_t) ((e->sync_type & ATSPI_KEYLISTENER_CANCONSUME)!=0);
115 listener_mode.global =
116 (dbus_bool_t) ((e->sync_type & ATSPI_KEYLISTENER_ALL_WINDOWS)!=0);
118 dbus_error_init (&d_error);
119 dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry,
120 atspi_path_dec, atspi_interface_dec,
121 "RegisterKeystrokeListener", &d_error,
122 "oa(iisi)uu(bbb)=>b", path, e->key_set,
123 e->modmask, e->event_types, &listener_mode,
125 if (dbus_error_is_set (&d_error))
127 g_warning ("RegisterKeystrokeListener failed: %s", d_error.message);
128 dbus_error_free (&d_error);
137 device_listener_entry_free (DeviceListenerEntry *e)
139 g_array_free (e->key_set, TRUE);
144 unregister_listener (gpointer data, GObject *object)
147 AtspiDeviceListener *listener = ATSPI_DEVICE_LISTENER (object);
149 for (l = device_listeners; l;)
151 DeviceListenerEntry *e = l->data;
152 if (e->listener == listener)
154 GList *next = l->next;
155 device_listener_entry_free (e);
156 device_listeners = g_list_delete_link (device_listeners, l);
165 * atspi_register_keystroke_listener:
166 * @listener: a pointer to the #AtspiDeviceListener for which
167 * keystroke events are requested.
168 * @key_set: (element-type AtspiKeyDefinition) (allow-none): a pointer to the
169 * #AtspiKeyDefinition array indicating which keystroke events are
171 * to indicate that all keycodes and keyvals for the specified
172 * modifier set are to be included.
173 * @modmask: an #AtspiKeyMaskType mask indicating which
174 * key event modifiers must be set in combination with @keys,
175 * events will only be reported for key events for which all
176 * modifiers in @modmask are set. If you wish to listen for
177 * events with multiple modifier combinations, you must call
178 * #atspi_register_keystroke_listener once for each
180 * @event_types: an #AtspiKeyMaskType mask indicating which
181 * types of key events are requested (%ATSPI_KEY_PRESSED etc.).
182 * @sync_type: an #AtspiKeyListenerSyncType parameter indicating
183 * the behavior of the notification/listener transaction.
184 * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
186 * Registers a listener for keystroke events, either pre-emptively for
187 * all windows (%ATSPI_KEYLISTENER_ALL_WINDOWS),
188 * non-preemptively (%ATSPI_KEYLISTENER_NOSYNC), or
189 * pre-emptively at the toolkit level (%ATSPI_KEYLISTENER_CANCONSUME).
190 * If ALL_WINDOWS or CANCONSUME are used, the event is consumed
191 * upon receipt if one of @listener's callbacks returns %TRUE
192 * (other sync_type values may be available in the future).
194 * Returns: %TRUE if successful, otherwise %FALSE.
197 atspi_register_keystroke_listener (AtspiDeviceListener *listener,
199 AtspiKeyMaskType modmask,
200 AtspiKeyEventMask event_types,
201 gint sync_type, GError **error)
203 DeviceListenerEntry *e;
205 g_return_val_if_fail (listener != NULL, FALSE);
207 e = g_new0 (DeviceListenerEntry, 1);
208 e->listener = listener;
209 e->modmask = modmask;
210 e->event_types = event_types;
211 e->sync_type = sync_type;
215 e->key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition),
217 e->key_set->len = key_set->len;
218 for (i = 0; i < key_set->len; i++)
220 AtspiKeyDefinition *kd = ((AtspiKeyDefinition *) key_set->data) + i;
221 AtspiKeyDefinition *d_kd = ((AtspiKeyDefinition *) e->key_set->data) + i;
222 d_kd->keycode = kd->keycode;
223 d_kd->keysym = kd->keysym;
226 d_kd->keystring = kd->keystring;
230 d_kd->keystring = "";
236 e->key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), 0);
239 g_object_weak_ref (G_OBJECT (listener), unregister_listener, NULL);
240 device_listeners = g_list_prepend (device_listeners, e);
241 return notify_keystroke_listener (e);
245 * atspi_deregister_keystroke_listener:
246 * @listener: a pointer to the #AtspiDeviceListener for which
247 * keystroke events are requested.
248 * @key_set: (element-type AtspiKeyDefinition) (allow-none): a pointer to the
249 * #AtspiKeyDefinition array indicating which keystroke events are
250 * requested, or %NULL
251 * to indicate that all keycodes and keyvals for the specified
252 * modifier set are to be included.
253 * @modmask: the key modifier mask for which this listener is to be
254 * 'deregistered' (of type #AtspiKeyMaskType).
255 * @event_types: an #AtspiKeyMaskType mask indicating which
256 * types of key events were requested (%ATSPI_KEY_PRESSED, etc.).
257 * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
259 * Removes a keystroke event listener from the registry's listener queue,
260 * ceasing notification of events with modifiers matching @modmask.
262 * Returns: %TRUE if successful, otherwise %FALSE.
265 atspi_deregister_keystroke_listener (AtspiDeviceListener *listener,
267 AtspiKeyMaskType modmask,
268 AtspiKeyEventMask event_types,
272 gchar *path = _atspi_device_listener_get_path (listener);
274 dbus_uint32_t d_modmask = modmask;
275 dbus_uint32_t d_event_types = event_types;
279 dbus_error_init (&d_error);
285 /* copy the keyval filter values from the C api into the DBind KeySet */
288 d_key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), key_set->len);
289 d_key_set->len = key_set->len;
290 for (i = 0; i < key_set->len; ++i)
292 AtspiKeyDefinition *kd = ((AtspiKeyDefinition *) key_set->data) + i;
293 AtspiKeyDefinition *d_kd = ((AtspiKeyDefinition *) d_key_set->data) + i;
294 d_kd->keycode = kd->keycode;
295 d_kd->keysym = kd->keysym;
298 d_kd->keystring = kd->keystring;
302 d_kd->keystring = "";
308 d_key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), 0);
311 dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry,
312 atspi_path_dec, atspi_interface_dec,
313 "DeregisterKeystrokeListener", &d_error,
314 "oa(iisi)uu", path, d_key_set, d_modmask,
316 if (dbus_error_is_set (&d_error))
318 g_warning ("DeregisterKeystrokeListener failed: %s", d_error.message);
319 dbus_error_free (&d_error);
322 unregister_listener (listener, NULL);
323 for (l = device_listeners; l;)
325 /* TODO: This code is all wrong / doesn't match what is in
326 * deviceeventcontroller.c. It would be nice to deprecate these methods
327 * in favor of methods that return an ID for the registration that can
328 * be passed to a deregister function, for instance. */
329 DeviceListenerEntry *e = l->data;
330 if (e->modmask == modmask && e->event_types == event_types)
332 GList *next = l->next;
333 device_listener_entry_free (e);
334 device_listeners = g_list_delete_link (device_listeners, l);
340 g_array_free (d_key_set, TRUE);
346 * atspi_register_device_event_listener:
347 * @listener: a pointer to the #AtspiDeviceListener which requests
349 * @event_types: an #AtspiDeviceEventMask mask indicating which
350 * types of key events are requested (%ATSPI_KEY_PRESSED, etc.).
351 * @filter: Unused parameter.
352 * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
354 * Registers a listener for device events, for instance button events.
356 * Returns: %TRUE if successful, otherwise %FALSE.
359 atspi_register_device_event_listener (AtspiDeviceListener *listener,
360 AtspiDeviceEventMask event_types,
361 void *filter, GError **error)
363 gboolean retval = FALSE;
364 dbus_uint32_t d_event_types = event_types;
365 gchar *path = _atspi_device_listener_get_path (listener);
368 dbus_error_init (&d_error);
374 dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "RegisterDeviceEventListener", &d_error, "ou=>b", path, d_event_types, &retval);
375 if (dbus_error_is_set (&d_error))
377 g_warning ("RegisterDeviceEventListener failed: %s", d_error.message);
378 dbus_error_free (&d_error);
386 * atspi_deregister_device_event_listener:
387 * @listener: a pointer to the #AtspiDeviceListener for which
388 * device events are requested.
389 * @filter: Unused parameter.
390 * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
392 * Removes a device event listener from the registry's listener queue,
393 * ceasing notification of events of the specified type.
395 * Returns: %TRUE if successful, otherwise %FALSE.
398 atspi_deregister_device_event_listener (AtspiDeviceListener *listener,
399 void *filter, GError **error)
401 dbus_uint32_t event_types = 0;
402 gchar *path = _atspi_device_listener_get_path (listener);
405 dbus_error_init (&d_error);
412 event_types |= (1 << ATSPI_BUTTON_PRESSED_EVENT);
413 event_types |= (1 << ATSPI_BUTTON_RELEASED_EVENT);
415 dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "DeregisterDeviceEventListener", &d_error, "ou", path, event_types);
416 if (dbus_error_is_set (&d_error))
418 g_warning ("DeregisterDeviceEventListener failed: %s", d_error.message);
419 dbus_error_free (&d_error);
427 * atspi_generate_keyboard_event:
428 * @keyval: a #gint indicating the keycode or keysym of the key event
430 * @keystring: (allow-none): an (optional) UTF-8 string which, if
431 * @synth_type is %ATSPI_KEY_STRING, indicates a 'composed'
432 * keyboard input string being synthesized; this type of
433 * keyboard event synthesis does not emulate hardware
434 * keypresses but injects the string as though a composing
435 * input method (such as XIM) were used.
436 * @synth_type: an #AtspiKeySynthType flag indicating whether @keyval
437 * is to be interpreted as a keysym rather than a keycode
438 * (%ATSPI_KEY_SYM) or a string (%ATSPI_KEY_STRING), or
439 * whether to synthesize %ATSPI_KEY_PRESS,
440 * %ATSPI_KEY_RELEASE, or both (%ATSPI_KEY_PRESSRELEASE).
441 * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
443 * Synthesizes a keyboard event (as if a hardware keyboard event occurred in the
444 * current UI context).
446 * Returns: %TRUE if successful, otherwise %FALSE.
449 atspi_generate_keyboard_event (glong keyval,
450 const gchar *keystring,
451 AtspiKeySynthType synth_type, GError **error)
453 dbus_uint32_t d_synth_type = synth_type;
454 dbus_int32_t d_keyval = keyval;
457 dbus_error_init (&d_error);
460 dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "GenerateKeyboardEvent", &d_error, "isu", d_keyval, keystring, d_synth_type);
461 if (dbus_error_is_set (&d_error))
463 g_warning ("GenerateKeyboardEvent failed: %s", d_error.message);
464 dbus_error_free (&d_error);
471 * atspi_generate_mouse_event:
472 * @x: a #glong indicating the screen x coordinate of the mouse event.
473 * @y: a #glong indicating the screen y coordinate of the mouse event.
474 * @name: a string indicating which mouse event to be synthesized
475 * (e.g. "b1p", "b1c", "b2r", "rel", "abs").
476 * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
478 * Synthesizes a mouse event at a specific screen coordinate.
479 * Most AT clients should use the #AccessibleAction interface when
480 * tempted to generate mouse events, rather than this method.
481 * Event names: b1p = button 1 press; b2r = button 2 release;
482 * b3c = button 3 click; b2d = button 2 double-click;
483 * abs = absolute motion; rel = relative motion.
485 * Returns: %TRUE if successful, otherwise %FALSE.
488 atspi_generate_mouse_event (glong x, glong y, const gchar *name, GError **error)
490 dbus_int32_t d_x = x, d_y = y;
493 dbus_error_init (&d_error);
494 dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry,
495 atspi_path_dec, atspi_interface_dec,
496 "GenerateMouseEvent", &d_error, "iis",
498 if (dbus_error_is_set (&d_error))
500 g_warning ("GenerateMouseEvent failed: %s", d_error.message);
501 dbus_error_free (&d_error);
508 atspi_key_definition_copy (AtspiKeyDefinition *src)
510 AtspiKeyDefinition *dst;
512 dst = g_new0 (AtspiKeyDefinition, 1);
513 dst->keycode = src->keycode;
514 dst->keysym = src->keysym;
516 dst->keystring = g_strdup (src->keystring);
517 dst->unused = src->unused;
522 atspi_key_definition_free (AtspiKeyDefinition *kd)
525 g_free (kd->keystring);
530 _atspi_reregister_device_listeners ()
533 DeviceListenerEntry *e;
535 for (l = device_listeners; l; l = l->next)
538 notify_keystroke_listener (e);
541 G_DEFINE_BOXED_TYPE (AtspiKeyDefinition, atspi_key_definition, atspi_key_definition_copy, atspi_key_definition_free)