X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=atspi%2Fatspi-registry.c;h=07af2c59262c7a573875253ea34fa13a6011238b;hb=d17bd107e0b8774c280aa8bf7682ec850ed9c439;hp=2e4763bc6b96d6e727323f980df4a57c0d96fdc3;hpb=11d647c36278e2430df5df0c56546e267971e74a;p=platform%2Fupstream%2Fat-spi2-core.git diff --git a/atspi/atspi-registry.c b/atspi/atspi-registry.c index 2e4763b..07af2c5 100644 --- a/atspi/atspi-registry.c +++ b/atspi/atspi-registry.c @@ -1,3 +1,4 @@ + /* * AT-SPI - Assistive Technology Service Provider Interface * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) @@ -25,16 +26,25 @@ #include "atspi-private.h" -static GArray *desktops; +typedef struct +{ + AtspiDeviceListener *listener; + GArray *key_set; + AtspiKeyMaskType modmask; + AtspiKeyEventMask event_types; + gint sync_type; +} DeviceListenerEntry; + +static GList *device_listeners; /** * atspi_get_desktop_count: * - * Get the number of virtual desktops. - * NOTE: currently multiple virtual desktops are not implemented, this - * function always returns '1'. + * Gets the number of virtual desktops. + * NOTE: multiple virtual desktops are not implemented yet; as a + * consequence, this function always returns 1. * - * Returns: an integer indicating the number of active virtual desktops. + * Returns: a #gint indicating the number of active virtual desktops. **/ gint atspi_get_desktop_count () @@ -44,13 +54,15 @@ atspi_get_desktop_count () /** * atspi_get_desktop: - * @i: an integer indicating which of the accessible desktops is to be returned. + * @i: a #gint indicating which of the accessible desktops is to be returned. * - * Get the virtual desktop indicated by index @i. - * NOTE: currently multiple virtual desktops are not implemented. + * Gets the virtual desktop indicated by index @i. + * NOTE: currently multiple virtual desktops are not implemented; + * as a consequence, any @i value different from 0 will not return a + * virtual desktop - instead it will return NULL. * - * Returns: a pointer to the 'i-th' virtual desktop's #AtspiAccessible - * representation. + * Returns: (transfer full): a pointer to the @i-th virtual desktop's + * #AtspiAccessible representation. **/ AtspiAccessible* atspi_get_desktop (gint i) @@ -61,21 +73,19 @@ atspi_get_desktop (gint i) /** * atspi_get_desktop_list: - * @desktop_list: a pointer to an array of #Accessible references. * - * Get the list of virtual desktops. On return, @list will point + * Gets the list of virtual desktops. On return, @list will point * to a newly-created, NULL terminated array of virtual desktop * pointers. * It is the responsibility of the caller to free this array when * it is no longer needed. + * NOTE: currently multiple virtual desktops are not implemented; + * this implementation always returns a #Garray with a single + * #AtspiAccessible desktop. * - * Not Yet Implemented : this implementation always returns a single - * #Accessible desktop. - * - * Returns: an integer indicating how many virtual desktops have been - * placed in the list pointed to by parameter @list. + * Returns: (element-type AtspiAccessible*) (transfer full): a #GArray of + * desktops. **/ -/* TODO: Make this a garray */ GArray * atspi_get_desktop_list () { @@ -88,147 +98,248 @@ atspi_get_desktop_list () return array; } -/** - * ATSPI_KEYSET_ALL_KEYS: - * @ATSPI_KEYSET_ALL_KEYS: A special value for an AccessibleKeySet type, which tacitly - * includes all keycodes and keyvals for the specified modifier set. - **/ +static gboolean +notify_keystroke_listener (DeviceListenerEntry *e) +{ + gchar *path = _atspi_device_listener_get_path (e->listener); + dbus_uint32_t d_modmask = e->modmask; + dbus_uint32_t d_event_types = e->event_types; + AtspiEventListenerMode listener_mode; + gboolean retval = FALSE; + DBusError d_error; + + listener_mode.synchronous = + (dbus_bool_t) ((e->sync_type & ATSPI_KEYLISTENER_SYNCHRONOUS)!=0); + listener_mode.preemptive = + (dbus_bool_t) ((e->sync_type & ATSPI_KEYLISTENER_CANCONSUME)!=0); + listener_mode.global = + (dbus_bool_t) ((e->sync_type & ATSPI_KEYLISTENER_ALL_WINDOWS)!=0); + + dbus_error_init (&d_error); + dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, + atspi_path_dec, atspi_interface_dec, + "RegisterKeystrokeListener", &d_error, + "oa(iisi)uu(bbb)=>b", path, e->key_set, + d_modmask, d_event_types, &listener_mode, + &retval); + if (dbus_error_is_set (&d_error)) + { + g_warning ("RegisterKeystrokeListener failed: %s", d_error.message); + dbus_error_free (&d_error); + } + + g_free (path); + + return retval; +} + +static void +device_listener_entry_free (DeviceListenerEntry *e) +{ + g_array_free (e->key_set, TRUE); + g_free (e); +} + +static void +unregister_listener (gpointer data, GObject *object) +{ + GList *l; + AtspiDeviceListener *listener = ATSPI_DEVICE_LISTENER (object); + + for (l = device_listeners; l;) + { + DeviceListenerEntry *e = l->data; + if (e->listener == listener) + { + GList *next = l->next; + device_listener_entry_free (e); + device_listeners = g_list_delete_link (device_listeners, l); + l = next; + } + else + l = l->next; + } +} /** - * atspi_register_accessible_keystroke_listener: - * @listener: a pointer to the #AccessibleKeystrokeListener for which + * atspi_register_keystroke_listener: + * @listener: a pointer to the #AtspiDeviceListener for which * keystroke events are requested. - * @keys: a pointer to the #AccessibleKeySet indicating which - * keystroke events are requested, or #ATSPI_KEYSET_ALL_KEYS - * to indicate that all keycodes and keyvals for the specified - * modifier set are to be included. - * @modmask: an #AccessibleKeyMaskType mask indicating which + * @key_set: (element-type AtspiKeyDefinition) (allow-none): a pointer to the + * #AtspiKeyDefinition array indicating which keystroke events are + * requested, or NULL + * to indicate that all keycodes and keyvals for the specified + * modifier set are to be included. + * @modmask: an #AtspiKeyMaskType mask indicating which * key event modifiers must be set in combination with @keys, * events will only be reported for key events for which all * modifiers in @modmask are set. If you wish to listen for - * events with multiple modifier combinations you must call - * registerAccessibleKeystrokeListener() once for each combination. - * @eventmask: an #AccessibleKeyMaskType mask indicating which - * types of key events are requested (#ATSPI_KEY_PRESSED, etc.). - * @sync_type: a #AccessibleKeyListenerSyncType parameter indicating + * events with multiple modifier combinations, you must call + * #atspi_register_keystroke_listener once for each + * combination. + * @event_types: an #AtspiKeyMaskType mask indicating which + * types of key events are requested (%ATSPI_KEY_PRESSED etc.). + * @sync_type: an #AtspiKeyListenerSyncType parameter indicating * the behavior of the notification/listener transaction. + * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL * - * Register a listener for keystroke events, either pre-emptively for - * all windows (ATSPI_KEYLISTENER_ALL_WINDOWS), - * non-preemptively (ATSPI_KEYLISTENER_NOSYNC), or - * pre-emptively at the toolkit level (ATSPI_KEYLISTENER_CANCONSUME). + * Registers a listener for keystroke events, either pre-emptively for + * all windows (%ATSPI_KEYLISTENER_ALL_WINDOWS), + * non-preemptively (%ATSPI_KEYLISTENER_NOSYNC), or + * pre-emptively at the toolkit level (%ATSPI_KEYLISTENER_CANCONSUME). * If ALL_WINDOWS or CANCONSUME are used, the event is consumed - * upon receipt if one of @listener's callbacks returns #TRUE. - * ( Other sync_type values may be available in the future ) + * upon receipt if one of @listener's callbacks returns %TRUE + * (other sync_type values may be available in the future). * - * Returns: #TRUE if successful, otherwise #FALSE. + * Returns: %TRUE if successful, otherwise %FALSE. **/ gboolean -atspi_register_accessible_keystroke_listener (AtspiKeystrokeListener *listener, - AtspiKeySet *keys, +atspi_register_keystroke_listener (AtspiDeviceListener *listener, + GArray *key_set, AtspiKeyMaskType modmask, - AtspiKeyEventMask eventmask, - AtspiKeyListenerSyncType sync_type, GError **error) + AtspiKeyEventMask event_types, + AtspiKeyListenerSyncType sync_type, + GError **error) { - gchar *path = _atspi_device_listener_get_path (listener); - gint i; - GArray *key_set; - dbus_uint32_t key_events = 0; - AtspiControllerEventMask controller_event_mask; - AtspiEventListenerMode listener_mode; - gboolean retval = FALSE; - DBusError d_error; + DeviceListenerEntry *e; - if (!listener) - { - return retval; - } + g_return_val_if_fail (listener != NULL, FALSE); - /* copy the keyval filter values from the C api into the DBind KeySet */ - if (keys) + e = g_new0 (DeviceListenerEntry, 1); + e->listener = listener; + e->modmask = modmask; + e->event_types = event_types; + e->sync_type = sync_type; + if (key_set) { - key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), keys->len); - key_set->len = keys->len; - for (i = 0; i < keys->len; ++i) + gint i; + e->key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), + key_set->len); + e->key_set->len = key_set->len; + for (i = 0; i < key_set->len; i++) { AtspiKeyDefinition *kd = ((AtspiKeyDefinition *) key_set->data) + i; - kd->keycode = keys->keycodes[i]; - kd->keysym = keys->keysyms[i]; - if (keys->keystrings && keys->keystrings[i]) + AtspiKeyDefinition *d_kd = ((AtspiKeyDefinition *) e->key_set->data) + i; + d_kd->keycode = kd->keycode; + d_kd->keysym = kd->keysym; + if (kd->keystring) { - kd->keystring = keys->keystrings[i]; + d_kd->keystring = kd->keystring; } else { - kd->keystring = ""; + d_kd->keystring = ""; } } } else { - key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), 0); - } - - /* copy the event filter values from the C api into the DBus key_events */ - if (eventmask & ATSPI_KEY_PRESSED) - { - key_events |= (1 << ATSPI_KEY_PRESSED_EVENT); - } - if (eventmask & ATSPI_KEY_RELEASED) - { - key_events |= (1 << ATSPI_KEY_RELEASED_EVENT); + e->key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), 0); } - - controller_event_mask = (dbus_uint32_t) modmask; - listener_mode.synchronous = - (dbus_bool_t) ((sync_type & ATSPI_KEYLISTENER_SYNCHRONOUS)!=0); - listener_mode.preemptive = - (dbus_bool_t) ((sync_type & ATSPI_KEYLISTENER_CANCONSUME)!=0); - listener_mode.global = - (dbus_bool_t) ((sync_type & ATSPI_KEYLISTENER_ALL_WINDOWS)!=0); - - dbus_error_init (&d_error); - dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "RegisterKeystrokeListener", &d_error, "oa(iisi)uu(bbb)=>b", path, key_set, controller_event_mask, key_events, &listener_mode, &retval); - - g_array_free (key_set, TRUE); - g_free (path); - - return retval; + g_object_weak_ref (G_OBJECT (listener), unregister_listener, NULL); + device_listeners = g_list_prepend (device_listeners, e); + return notify_keystroke_listener (e); } /** - * atspi_deregister_accessible_keystroke_listener: - * @listener: a pointer to the #AccessibleKeystrokeListener for which + * atspi_deregister_keystroke_listener: + * @listener: a pointer to the #AtspiDeviceListener for which * keystroke events are requested. + * @key_set: (element-type AtspiKeyDefinition) (allow-none): a pointer to the + * #AtspiKeyDefinition array indicating which keystroke events are + * requested, or %NULL + * to indicate that all keycodes and keyvals for the specified + * modifier set are to be included. * @modmask: the key modifier mask for which this listener is to be * 'deregistered' (of type #AtspiKeyMaskType). + * @event_types: an #AtspiKeyMaskType mask indicating which + * types of key events were requested (%ATSPI_KEY_PRESSED, etc.). + * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL * * Removes a keystroke event listener from the registry's listener queue, * ceasing notification of events with modifiers matching @modmask. * - * Returns: #TRUE if successful, otherwise #FALSE. + * Returns: %TRUE if successful, otherwise %FALSE. **/ gboolean -atspi_deregister_accessible_keystroke_listener (AtspiKeystrokeListener *listener, - AtspiKeyMaskType modmask, GError **error) +atspi_deregister_keystroke_listener (AtspiDeviceListener *listener, + GArray *key_set, + AtspiKeyMaskType modmask, + AtspiKeyEventMask event_types, + GError **error) { - gchar *path = _atspi_device_listener_get_path (listener); - AtspiControllerEventMask controller_event_mask; - GArray *key_set; - dbus_uint32_t key_events = 0; + GArray *d_key_set; + gchar *path; + gint i; + dbus_uint32_t d_modmask = modmask; + dbus_uint32_t d_event_types = event_types; DBusError d_error; + GList *l; dbus_error_init (&d_error); if (!listener) { return FALSE; } + path = _atspi_device_listener_get_path (listener); + + /* copy the keyval filter values from the C api into the DBind KeySet */ + if (key_set) + { + d_key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), key_set->len); + d_key_set->len = key_set->len; + for (i = 0; i < key_set->len; ++i) + { + AtspiKeyDefinition *kd = ((AtspiKeyDefinition *) key_set->data) + i; + AtspiKeyDefinition *d_kd = ((AtspiKeyDefinition *) d_key_set->data) + i; + d_kd->keycode = kd->keycode; + d_kd->keysym = kd->keysym; + if (kd->keystring) + { + d_kd->keystring = kd->keystring; + } + else + { + d_kd->keystring = ""; + } + } + } + else + { + d_key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), 0); + } - controller_event_mask = (dbus_uint32_t) modmask; + dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, + atspi_path_dec, atspi_interface_dec, + "DeregisterKeystrokeListener", &d_error, + "oa(iisi)uu", path, d_key_set, d_modmask, + d_event_types); + if (dbus_error_is_set (&d_error)) + { + g_warning ("DeregisterKeystrokeListener failed: %s", d_error.message); + dbus_error_free (&d_error); + } - key_set = g_array_sized_new (FALSE, TRUE, sizeof (AtspiKeyDefinition), 0); - dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "DeregisterKeystrokeListener", &d_error, "oa(iisi)uu", path, &key_set, key_events, controller_event_mask); + unregister_listener (listener, NULL); + for (l = device_listeners; l;) + { + /* TODO: This code is all wrong / doesn't match what is in + * deviceeventcontroller.c. It would be nice to deprecate these methods + * in favor of methods that return an ID for the registration that can + * be passed to a deregister function, for instance. */ + DeviceListenerEntry *e = l->data; + if (e->modmask == modmask && e->event_types == event_types) + { + GList *next = l->next; + device_listener_entry_free (e); + device_listeners = g_list_delete_link (device_listeners, l); + l = next; + } + else + l = l->next; + } + g_array_free (d_key_set, TRUE); g_free (path); return TRUE; } @@ -237,23 +348,23 @@ atspi_deregister_accessible_keystroke_listener (AtspiKeystrokeListener *listener * atspi_register_device_event_listener: * @listener: a pointer to the #AtspiDeviceListener which requests * the events. - * @eventmask: an #AtspiDeviceEventMask mask indicating which - * types of key events are requested (#ATSPI_KEY_PRESSED, etc.). - * @filter: Unused parameter. + * @event_types: an #AtspiDeviceEventMask mask indicating which + * types of key events are requested (%ATSPI_KEY_PRESSED, etc.). + * @filter: (allow-none): Unused parameter. + * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL * - * Register a listener for device events, for instance button events. + * Registers a listener for device events, for instance button events. * - * Returns: #TRUE if successful, otherwise #FALSE. + * Returns: %TRUE if successful, otherwise %FALSE. **/ gboolean atspi_register_device_event_listener (AtspiDeviceListener *listener, - AtspiDeviceEventMask event_mask, + AtspiDeviceEventMask event_types, void *filter, GError **error) { gboolean retval = FALSE; - dbus_uint32_t d_event_mask = event_mask; - gint i; - gchar *path = _atspi_device_listener_get_path (listener); + dbus_uint32_t d_event_types = event_types; + gchar *path; DBusError d_error; dbus_error_init (&d_error); @@ -261,8 +372,15 @@ atspi_register_device_event_listener (AtspiDeviceListener *listener, { return retval; } + path = _atspi_device_listener_get_path (listener); + + 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); + if (dbus_error_is_set (&d_error)) + { + g_warning ("RegisterDeviceEventListener failed: %s", d_error.message); + dbus_error_free (&d_error); + } - dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "RegisterDeviceEventListener", &d_error, "ou=>b", path, d_event_mask, &retval); g_free (path); return retval; } @@ -271,19 +389,20 @@ atspi_register_device_event_listener (AtspiDeviceListener *listener, * atspi_deregister_device_event_listener: * @listener: a pointer to the #AtspiDeviceListener for which * device events are requested. - * @filter: Unused parameter. + * @filter: (allow-none): Unused parameter. + * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL * * Removes a device event listener from the registry's listener queue, * ceasing notification of events of the specified type. * - * Returns: #TRUE if successful, otherwise #FALSE. + * Returns: %TRUE if successful, otherwise %FALSE. **/ gboolean atspi_deregister_device_event_listener (AtspiDeviceListener *listener, void *filter, GError **error) { dbus_uint32_t event_types = 0; - gchar *path = _atspi_device_listener_get_path (listener); + gchar *path; DBusError d_error; dbus_error_init (&d_error); @@ -292,33 +411,44 @@ atspi_deregister_device_event_listener (AtspiDeviceListener *listener, { return FALSE; } + path = _atspi_device_listener_get_path (listener); event_types |= (1 << ATSPI_BUTTON_PRESSED_EVENT); event_types |= (1 << ATSPI_BUTTON_RELEASED_EVENT); - dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "DeregisterDeviceEventListener", &d_error, "ou", path, event_types); + dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "DeregisterDeviceEventListener", &d_error, "ou", path, event_types); + if (dbus_error_is_set (&d_error)) + { + g_warning ("DeregisterDeviceEventListener failed: %s", d_error.message); + dbus_error_free (&d_error); + } + g_free (path); return TRUE; } /** * atspi_generate_keyboard_event: - * @keyval: a long integer indicating the keycode or keysym of the key event - * being synthesized. - * @keystring: an (optional) UTF-8 string which, if @keyval is NULL, - * indicates a 'composed' keyboard input string which is - * being synthesized; this type of keyboard event synthesis does - * not emulate hardware keypresses but injects the string - * as though a composing input method (such as XIM) were used. - * @synth_type: a #AccessibleKeySynthType flag indicating whether @keyval + * @keyval: a #gint indicating the keycode or keysym or modifier mask of the + * key event being synthesized. + * @keystring: (allow-none): an (optional) UTF-8 string which, if + * @synth_type is %ATSPI_KEY_STRING, indicates a 'composed' + * keyboard input string being synthesized; this type of + * keyboard event synthesis does not emulate hardware + * keypresses but injects the string as though a composing + * input method (such as XIM) were used. + * @synth_type: an #AtspiKeySynthType flag indicating whether @keyval * is to be interpreted as a keysym rather than a keycode - * (ATSPI_KEYSYM), or whether to synthesize - * ATSPI_KEY_PRESS, ATSPI_KEY_RELEASE, or both (ATSPI_KEY_PRESSRELEASE). + * (%ATSPI_KEY_SYM) or a string (%ATSPI_KEY_STRING) or a modifier + * mask (%ATSPI_KEY_LOCKMODIFIERS and %ATSPI_KEY_UNLOCKMODIFIERS), or + * whether to synthesize %ATSPI_KEY_PRESS, + * %ATSPI_KEY_RELEASE, or both (%ATSPI_KEY_PRESSRELEASE). + * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL * - * Synthesize a keyboard event (as if a hardware keyboard event occurred in the + * Synthesizes a keyboard event (as if a hardware keyboard event occurred in the * current UI context). * - * Returns: #TRUE if successful, otherwise #FALSE. + * Returns: %TRUE if successful, otherwise %FALSE. **/ gboolean atspi_generate_keyboard_event (glong keyval, @@ -330,35 +460,87 @@ atspi_generate_keyboard_event (glong keyval, DBusError d_error; dbus_error_init (&d_error); - if (!keystring) keystring = ""; - 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); + if (!keystring) + keystring = ""; + 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); + if (dbus_error_is_set (&d_error)) + { + g_warning ("GenerateKeyboardEvent failed: %s", d_error.message); + dbus_error_free (&d_error); + } return TRUE; } /** * atspi_generate_mouse_event: - * @x: a #long indicating the screen x coordinate of the mouse event. - * @y: a #long indicating the screen y coordinate of the mouse event. + * @x: a #glong indicating the screen x coordinate of the mouse event. + * @y: a #glong indicating the screen y coordinate of the mouse event. * @name: a string indicating which mouse event to be synthesized * (e.g. "b1p", "b1c", "b2r", "rel", "abs"). + * @error: (allow-none): a pointer to a %NULL #GError pointer, or %NULL * - * Synthesize a mouse event at a specific screen coordinate. + * Synthesizes a mouse event at a specific screen coordinate. * Most AT clients should use the #AccessibleAction interface when * tempted to generate mouse events, rather than this method. * Event names: b1p = button 1 press; b2r = button 2 release; * b3c = button 3 click; b2d = button 2 double-click; * abs = absolute motion; rel = relative motion. * - * Returns: #TRUE if successful, otherwise #FALSE. + * Returns: %TRUE if successful, otherwise %FALSE. **/ gboolean atspi_generate_mouse_event (glong x, glong y, const gchar *name, GError **error) { - dbus_int32_t dbus_x = x, dbus__y = y; + dbus_int32_t d_x = x, d_y = y; DBusError d_error; dbus_error_init (&d_error); - dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, atspi_path_dec, atspi_interface_dec, "GenerateMouseEvent", &d_error, "iis", x, y, name); + dbind_method_call_reentrant (_atspi_bus(), atspi_bus_registry, + atspi_path_dec, atspi_interface_dec, + "GenerateMouseEvent", &d_error, "iis", + d_x, d_y, name); + if (dbus_error_is_set (&d_error)) + { + g_warning ("GenerateMouseEvent failed: %s", d_error.message); + dbus_error_free (&d_error); + } + return TRUE; } + +AtspiKeyDefinition * +atspi_key_definition_copy (AtspiKeyDefinition *src) +{ + AtspiKeyDefinition *dst; + + dst = g_new0 (AtspiKeyDefinition, 1); + dst->keycode = src->keycode; + dst->keysym = src->keysym; + if (src->keystring) + dst->keystring = g_strdup (src->keystring); + dst->unused = src->unused; + return dst; +} + +void +atspi_key_definition_free (AtspiKeyDefinition *kd) +{ + if (kd->keystring) + g_free (kd->keystring); + g_free (kd); +} + +void +_atspi_reregister_device_listeners () +{ + GList *l; + DeviceListenerEntry *e; + + for (l = device_listeners; l; l = l->next) + { + e = l->data; + notify_keystroke_listener (e); + } +} +G_DEFINE_BOXED_TYPE (AtspiKeyDefinition, atspi_key_definition, atspi_key_definition_copy, atspi_key_definition_free)