Merge upstream branch 2.31.1 into branch origin/tizen
[platform/upstream/at-spi2-core.git] / atspi / atspi-registry.c
index 2e4763b..07af2c5 100644 (file)
@@ -1,3 +1,4 @@
+
 /*
  * AT-SPI - Assistive Technology Service Provider Interface
  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
 
 #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)