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 Lesser General Public
11 * License as published by the Free Software Foundation; either
12 * version 2.1 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 * Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public
20 * License along with this library; if not, write to the
21 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
22 * Boston, MA 02110-1301, 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: (element-type AtspiAccessible*) (transfer full): a #GArray of
90 atspi_get_desktop_list ()
92 GArray *array = g_array_new (TRUE, TRUE, sizeof (AtspiAccessible *));
93 AtspiAccessible *desktop;
95 desktop = _atspi_ref_accessible (atspi_bus_registry, atspi_path_root);
97 g_array_index (array, AtspiAccessible *, 0) = desktop;
102 //TIZEN_ONLY(20211206) Provide GetActiveWindow
104 * atspi_get_active_window:
106 * Gets recently activated window.
107 * NOTE: the Tizen only interface for multiple AT-clients
109 * Returns: (transfer full): a pointer to active window's
110 * #AtspiAccessible representation.
113 atspi_get_active_window ()
115 DBusMessage *message, *reply;
116 DBusMessageIter iter;
117 AtspiAccessible* active_window;
119 message = dbus_message_new_method_call (ATSPI_DBUS_NAME_REGISTRY,
120 ATSPI_DBUS_PATH_REGISTRY,
121 ATSPI_DBUS_INTERFACE_REGISTRY,
126 reply = _atspi_dbus_send_with_reply_and_block (message, NULL);
130 if (strcmp (dbus_message_get_signature (reply), "(so)") != 0)
132 dbus_message_unref (reply);
136 dbus_message_iter_init (reply, &iter);
137 active_window = _atspi_dbus_return_accessible_from_iter (&iter);
139 dbus_message_unref (reply);
144 return g_object_ref (active_window);
148 * atspi_get_foreground_windows:
150 * Gets the array of foreground windows On return, @array will point
151 * to a newly-created, NULL terminated array of foreground window
153 * It is the responsibility of the caller to free this array when
154 * it is no longer needed.
156 * Returns: (element-type AtspiAccessible*) (transfer full): a #GArray of
157 * foreground windows.
160 atspi_get_foreground_windows ()
162 DBusMessage *message, *reply;
163 DBusMessageIter iter, iter_array, iter_dict;
166 message = dbus_message_new_method_call (ATSPI_DBUS_NAME_REGISTRY,
167 ATSPI_DBUS_PATH_REGISTRY,
168 ATSPI_DBUS_INTERFACE_REGISTRY,
169 "GetForegroundWindows");
173 reply = _atspi_dbus_send_with_reply_and_block (message, NULL);
177 if (strcmp (dbus_message_get_signature (reply), "a(so)") != 0)
179 dbus_message_unref (reply);
183 dbus_message_iter_init (reply, &iter);
184 ret = g_array_new (TRUE, TRUE, sizeof (AtspiAccessible *));
186 dbus_message_iter_recurse (&iter, &iter_array);
187 while (dbus_message_iter_get_arg_type (&iter_array) != DBUS_TYPE_INVALID)
189 const char *name, *path;
190 AtspiAccessible *accessible;
191 dbus_message_iter_recurse (&iter_array, &iter_dict);
192 dbus_message_iter_get_basic (&iter_dict, &name);
193 dbus_message_iter_next (&iter_dict);
194 dbus_message_iter_get_basic (&iter_dict, &path);
195 accessible = ref_accessible(name, path);
196 ret = g_array_append_val (ret, accessible);
197 dbus_message_iter_next (&iter_array);
199 dbus_message_unref (reply);
206 notify_keystroke_listener (DeviceListenerEntry *e)
208 gchar *path = _atspi_device_listener_get_path (e->listener);
209 dbus_uint32_t d_modmask = e->modmask;
210 dbus_uint32_t d_event_types = e->event_types;
211 AtspiEventListenerMode listener_mode;
212 gboolean retval = FALSE;
215 listener_mode.synchronous =
216 (dbus_bool_t) ((e->sync_type & ATSPI_KEYLISTENER_SYNCHRONOUS)!=0);
217 listener_mode.preemptive =
218 (dbus_bool_t) ((e->sync_type & ATSPI_KEYLISTENER_CANCONSUME)!=0);
219 listener_mode.global =
220 (dbus_bool_t) ((e->sync_type & ATSPI_KEYLISTENER_ALL_WINDOWS)!=0);
222 dbus_error_init (&d_error);
223 dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry,
224 atspi_path_dec, atspi_interface_dec,
225 "RegisterKeystrokeListener", &d_error,
226 "oa(iisi)uu(bbb)=>b", path, e->key_set,
227 d_modmask, d_event_types, &listener_mode,
229 if (dbus_error_is_set (&d_error))
231 g_warning ("RegisterKeystrokeListener failed: %s", d_error.message);
232 dbus_error_free (&d_error);
241 device_listener_entry_free (DeviceListenerEntry *e)
243 g_array_free (e->key_set, TRUE);
248 unregister_listener (gpointer data, GObject *object)
251 AtspiDeviceListener *listener = ATSPI_DEVICE_LISTENER (object);
253 for (l = device_listeners; l;)
255 DeviceListenerEntry *e = l->data;
256 if (e->listener == listener)
258 GList *next = l->next;
259 device_listener_entry_free (e);
260 device_listeners = g_list_delete_link (device_listeners, l);
269 * atspi_register_keystroke_listener:
270 * @listener: a pointer to the #AtspiDeviceListener for which
271 * keystroke events are requested.
272 * @key_set: (element-type AtspiKeyDefinition) (allow-none): a pointer to the
273 * #AtspiKeyDefinition array indicating which keystroke events are
275 * to indicate that all keycodes and keyvals for the specified
276 * modifier set are to be included.
277 * @modmask: an #AtspiKeyMaskType mask indicating which
278 * key event modifiers must be set in combination with @keys,
279 * events will only be reported for key events for which all
280 * modifiers in @modmask are set. If you wish to listen for
281 * events with multiple modifier combinations, you must call
282 * #atspi_register_keystroke_listener once for each
284 * @event_types: an #AtspiKeyMaskType mask indicating which
285 * types of key events are requested (%ATSPI_KEY_PRESSED etc.).
286 * @sync_type: an #AtspiKeyListenerSyncType parameter indicating
287 * the behavior of the notification/listener transaction.
288 * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
290 * Registers a listener for keystroke events, either pre-emptively for
291 * all windows (%ATSPI_KEYLISTENER_ALL_WINDOWS),
292 * non-preemptively (%ATSPI_KEYLISTENER_NOSYNC), or
293 * pre-emptively at the toolkit level (%ATSPI_KEYLISTENER_CANCONSUME).
294 * If ALL_WINDOWS or CANCONSUME are used, the event is consumed
295 * upon receipt if one of @listener's callbacks returns %TRUE
296 * (other sync_type values may be available in the future).
298 * Returns: %TRUE if successful, otherwise %FALSE.
301 atspi_register_keystroke_listener (AtspiDeviceListener *listener,
303 AtspiKeyMaskType modmask,
304 AtspiKeyEventMask event_types,
305 AtspiKeyListenerSyncType sync_type,
308 DeviceListenerEntry *e;
310 g_return_val_if_fail (listener != NULL, FALSE);
312 e = g_new0 (DeviceListenerEntry, 1);
313 e->listener = listener;
314 e->modmask = modmask;
315 e->event_types = event_types;
316 e->sync_type = sync_type;
320 e->key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition),
322 e->key_set->len = key_set->len;
323 for (i = 0; i < key_set->len; i++)
325 AtspiKeyDefinition *kd = ((AtspiKeyDefinition *) key_set->data) + i;
326 AtspiKeyDefinition *d_kd = ((AtspiKeyDefinition *) e->key_set->data) + i;
327 d_kd->keycode = kd->keycode;
328 d_kd->keysym = kd->keysym;
331 d_kd->keystring = kd->keystring;
335 d_kd->keystring = "";
341 e->key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), 0);
344 g_object_weak_ref (G_OBJECT (listener), unregister_listener, NULL);
345 device_listeners = g_list_prepend (device_listeners, e);
346 return notify_keystroke_listener (e);
350 * atspi_deregister_keystroke_listener:
351 * @listener: a pointer to the #AtspiDeviceListener for which
352 * keystroke events are requested.
353 * @key_set: (element-type AtspiKeyDefinition) (allow-none): a pointer to the
354 * #AtspiKeyDefinition array indicating which keystroke events are
355 * requested, or %NULL
356 * to indicate that all keycodes and keyvals for the specified
357 * modifier set are to be included.
358 * @modmask: the key modifier mask for which this listener is to be
359 * 'deregistered' (of type #AtspiKeyMaskType).
360 * @event_types: an #AtspiKeyMaskType mask indicating which
361 * types of key events were requested (%ATSPI_KEY_PRESSED, etc.).
362 * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
364 * Removes a keystroke event listener from the registry's listener queue,
365 * ceasing notification of events with modifiers matching @modmask.
367 * Returns: %TRUE if successful, otherwise %FALSE.
370 atspi_deregister_keystroke_listener (AtspiDeviceListener *listener,
372 AtspiKeyMaskType modmask,
373 AtspiKeyEventMask event_types,
379 dbus_uint32_t d_modmask = modmask;
380 dbus_uint32_t d_event_types = event_types;
389 dbus_error_init (&d_error);
391 path = _atspi_device_listener_get_path (listener);
393 /* copy the keyval filter values from the C api into the DBind KeySet */
396 d_key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), key_set->len);
397 d_key_set->len = key_set->len;
398 for (i = 0; i < key_set->len; ++i)
400 AtspiKeyDefinition *kd = ((AtspiKeyDefinition *) key_set->data) + i;
401 AtspiKeyDefinition *d_kd = ((AtspiKeyDefinition *) d_key_set->data) + i;
402 d_kd->keycode = kd->keycode;
403 d_kd->keysym = kd->keysym;
406 d_kd->keystring = kd->keystring;
410 d_kd->keystring = "";
416 d_key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), 0);
419 dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry,
420 atspi_path_dec, atspi_interface_dec,
421 "DeregisterKeystrokeListener", &d_error,
422 "oa(iisi)uu", path, d_key_set, d_modmask,
424 if (dbus_error_is_set (&d_error))
426 g_warning ("DeregisterKeystrokeListener failed: %s", d_error.message);
427 dbus_error_free (&d_error);
430 unregister_listener (listener, NULL);
431 for (l = device_listeners; l;)
433 /* TODO: This code is all wrong / doesn't match what is in
434 * deviceeventcontroller.c. It would be nice to deprecate these methods
435 * in favor of methods that return an ID for the registration that can
436 * be passed to a deregister function, for instance. */
437 DeviceListenerEntry *e = l->data;
438 if (e->modmask == modmask && e->event_types == event_types)
440 GList *next = l->next;
441 device_listener_entry_free (e);
442 device_listeners = g_list_delete_link (device_listeners, l);
448 g_array_free (d_key_set, TRUE);
454 * atspi_register_device_event_listener:
455 * @listener: a pointer to the #AtspiDeviceListener which requests
457 * @event_types: an #AtspiDeviceEventMask mask indicating which
458 * types of key events are requested (%ATSPI_KEY_PRESSED, etc.).
459 * @filter: (allow-none): Unused parameter.
460 * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
462 * Registers a listener for device events, for instance button events.
464 * Returns: %TRUE if successful, otherwise %FALSE.
467 atspi_register_device_event_listener (AtspiDeviceListener *listener,
468 AtspiDeviceEventMask event_types,
469 void *filter, GError **error)
471 gboolean retval = FALSE;
472 dbus_uint32_t d_event_types = event_types;
481 dbus_error_init (&d_error);
483 path = _atspi_device_listener_get_path (listener);
485 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);
486 if (dbus_error_is_set (&d_error))
488 g_warning ("RegisterDeviceEventListener failed: %s", d_error.message);
489 dbus_error_free (&d_error);
497 * atspi_deregister_device_event_listener:
498 * @listener: a pointer to the #AtspiDeviceListener for which
499 * device events are requested.
500 * @filter: (allow-none): Unused parameter.
501 * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
503 * Removes a device event listener from the registry's listener queue,
504 * ceasing notification of events of the specified type.
506 * Returns: %TRUE if successful, otherwise %FALSE.
509 atspi_deregister_device_event_listener (AtspiDeviceListener *listener,
510 void *filter, GError **error)
512 dbus_uint32_t event_types = 0;
521 dbus_error_init (&d_error);
523 path = _atspi_device_listener_get_path (listener);
525 event_types |= (1 << ATSPI_BUTTON_PRESSED_EVENT);
526 event_types |= (1 << ATSPI_BUTTON_RELEASED_EVENT);
528 dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "DeregisterDeviceEventListener", &d_error, "ou", path, event_types);
529 if (dbus_error_is_set (&d_error))
531 g_warning ("DeregisterDeviceEventListener failed: %s", d_error.message);
532 dbus_error_free (&d_error);
542 return (g_getenv ("WAYLAND_DISPLAY") != NULL);
546 * atspi_generate_keyboard_event:
547 * @keyval: a #gint indicating the keycode or keysym or modifier mask of the
548 * key event being synthesized.
549 * @keystring: (allow-none): an (optional) UTF-8 string which, if
550 * @synth_type is %ATSPI_KEY_STRING, indicates a 'composed'
551 * keyboard input string being synthesized; this type of
552 * keyboard event synthesis does not emulate hardware
553 * keypresses but injects the string as though a composing
554 * input method (such as XIM) were used.
555 * @synth_type: an #AtspiKeySynthType flag indicating whether @keyval
556 * is to be interpreted as a keysym rather than a keycode
557 * (%ATSPI_KEY_SYM) or a string (%ATSPI_KEY_STRING) or a modifier
558 * mask (%ATSPI_KEY_LOCKMODIFIERS and %ATSPI_KEY_UNLOCKMODIFIERS), or
559 * whether to synthesize %ATSPI_KEY_PRESS,
560 * %ATSPI_KEY_RELEASE, or both (%ATSPI_KEY_PRESSRELEASE).
561 * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
563 * Synthesizes a keyboard event (as if a hardware keyboard event occurred in the
564 * current UI context).
566 * Returns: %TRUE if successful, otherwise %FALSE.
569 atspi_generate_keyboard_event (glong keyval,
570 const gchar *keystring,
571 AtspiKeySynthType synth_type, GError **error)
573 dbus_uint32_t d_synth_type = synth_type;
574 dbus_int32_t d_keyval = keyval;
579 if (_atspi_mutter_generate_keyboard_event (keyval, keystring, synth_type, error))
583 dbus_error_init (&d_error);
586 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);
587 if (dbus_error_is_set (&d_error))
589 g_warning ("GenerateKeyboardEvent failed: %s", d_error.message);
590 dbus_error_free (&d_error);
597 * atspi_generate_mouse_event:
598 * @x: a #glong indicating the screen x coordinate of the mouse event.
599 * @y: a #glong indicating the screen y coordinate of the mouse event.
600 * @name: a string indicating which mouse event to be synthesized
601 * (e.g. "b1p", "b1c", "b2r", "rel", "abs").
602 * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL
604 * Synthesizes a mouse event at a specific screen coordinate.
605 * Most AT clients should use the #AccessibleAction interface when
606 * tempted to generate mouse events, rather than this method.
607 * Event names: b1p = button 1 press; b2r = button 2 release;
608 * b3c = button 3 click; b2d = button 2 double-click;
609 * abs = absolute motion; rel = relative motion.
611 * Returns: %TRUE if successful, otherwise %FALSE.
614 atspi_generate_mouse_event (glong x, glong y, const gchar *name, GError **error)
616 dbus_int32_t d_x = x, d_y = y;
619 g_return_val_if_fail (name != NULL, FALSE);
623 if (_atspi_mutter_generate_mouse_event (x, y, name, error))
627 dbus_error_init (&d_error);
628 dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry,
629 atspi_path_dec, atspi_interface_dec,
630 "GenerateMouseEvent", &d_error, "iis",
632 if (dbus_error_is_set (&d_error))
634 g_warning ("GenerateMouseEvent failed: %s", d_error.message);
635 dbus_error_free (&d_error);
642 * atspi_set_reference_window:
643 * @accessible: the #AtspiAccessible corresponding to the window to select.
644 * should be a top-level window with a role of
645 * ATSPI_ROLE_APPLICATION.
647 * Sets the reference window that will be used when atspi_generate_mouse_event
648 * is called. Coordinates will be assumed to be relative to this window. This
649 * is needed because, due to Wayland's security model, it is not currently
650 * possible to retrieve global coordinates.
651 * If NULL is passed, then AT-SPI will use the window that has focus at the
652 * time that atspi_generate_mouse_event is called.
655 atspi_set_reference_window (AtspiAccessible *accessible)
658 _atspi_mutter_set_reference_window (accessible);
662 atspi_key_definition_copy (AtspiKeyDefinition *src)
664 AtspiKeyDefinition *dst;
666 dst = g_new0 (AtspiKeyDefinition, 1);
667 dst->keycode = src->keycode;
668 dst->keysym = src->keysym;
670 dst->keystring = g_strdup (src->keystring);
671 dst->modifiers = src->modifiers;
676 atspi_key_definition_free (AtspiKeyDefinition *kd)
679 g_free (kd->keystring);
684 _atspi_reregister_device_listeners ()
687 DeviceListenerEntry *e;
689 for (l = device_listeners; l; l = l->next)
692 notify_keystroke_listener (e);
695 G_DEFINE_BOXED_TYPE (AtspiKeyDefinition, atspi_key_definition, atspi_key_definition_copy, atspi_key_definition_free)