Add .po and .pc files from cspi
[platform/core/uifw/at-spi2-atk.git] / cspi / spi_registry.c
index b7005a2..48b84d8 100644 (file)
@@ -2,7 +2,8 @@
  * AT-SPI - Assistive Technology Service Provider Interface
  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
  *
- * Copyright 2001 Sun Microsystems Inc.
+ * Copyright 2001, 2002 Sun Microsystems Inc.,
+ * Copyright 2001, 2002 Ximian, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
 
 #include <cspi/spi-private.h>
 
-/**
- * registerGlobalEventListener:
- * @listener: the #AccessibleEventListener to be registered against an
- *            event type.
- * @eventType: a character string indicating the type of events for which
- *            notification is requested.  Format is
- *            EventClass:major_type:minor_type:detail
- *            where all subfields other than EventClass are optional.
- *            EventClasses include "object", "window", "mouse",
- *            and toolkit events (e.g. "Gtk", "AWT").
- *            Examples: "focus:", "Gtk:GtkWidget:button_press_event".
- *
- * Legal object event types:
- *
- *    (property change events)
- *
- *            object:property-change
- *            object:property-change:accessible-name
- *            object:property-change:accessible-state
- *            object:property-change:accessible-description
- *            object:property-change:accessible-parent
- *            object:property-change:accessible-value
- *            object:property-change:accessible-role
- *            object:property-change:accessible-table-caption
- *            object:property-change:accessible-table-column-description
- *            object:property-change:accessible-table-column-header
- *            object:property-change:accessible-table-row-description
- *            object:property-change:accessible-table-row-header
- *            object:property-change:accessible-table-summary
- *
- *    (other object events)
- *
- *            object:children-changed
- *            object:visible-data-changed
- *            object:selection-changed
- *            object:text-selection-changed
- *            object:text-changed
- *            object:text-caret-moved
- *            object:row-inserted
- *            object:row-reordered
- *            object:row-deleted
- *            object:column-inserted
- *            object:column-reordered
- *            object:column-deleted
- *            object:model-changed
- *
- * NOTE: this string may be UTF-8, but should not contain byte value 56
- *            (ascii ':'), except as a delimiter, since non-UTF-8 string
- *            delimiting functions are used internally.
- *            In general, listening to
- *            toolkit-specific events is not recommended.
- *
- * Add an in-process callback function to an existing AccessibleEventListener.
- *
- * Returns: #TRUE if successful, otherwise #FALSE.
- *
- **/
-SPIBoolean
-registerGlobalEventListener (AccessibleEventListener *listener,
-                             const char              *eventType)
-{
-  SPIBoolean retval;
-
-  Accessibility_Registry_registerGlobalEventListener (
-                         cspi_registry (),
-                         (Accessibility_EventListener)
-                            BONOBO_OBJREF (bonobo_object (listener)),
-                         eventType,
-                         cspi_ev ());
+static GArray *desktops;
 
-  retval = !cspi_exception ();
-  return retval;
-}
-
-/**
- * deregisterGlobalEventListenerAll:
- * @listener: the #AccessibleEventListener to be registered against
- *            an event type.
- *
- * deregisters an AccessibleEventListener from the registry, for all
- *            event types it may be listening to. Use
- *            AccessibleEventListener_unref to release the
- *            listener reference.
- *
- * Returns: #TRUE if successful, otherwise #FALSE.
- *
- **/
-SPIBoolean
-deregisterGlobalEventListenerAll (AccessibleEventListener *listener)
-{
-  Accessibility_Registry_deregisterGlobalEventListenerAll (
-                         cspi_registry (),
-                        (Accessibility_EventListener) BONOBO_OBJREF (listener),
-                        cspi_ev ());
-
-  return !cspi_exception ();
-}
 /**
- * deregisterGlobalEventListener:
- * @listener: the #AccessibleEventListener registered against an event type.
- * @eventType: a string specifying the event type for which this
- *             listener is to be deregistered.
- *
- * deregisters an AccessibleEventListener from the registry, for a specific
- *             event type.
- *
- * Returns: #TRUE if successful, otherwise #FALSE.
- *
- **/
-SPIBoolean
-deregisterGlobalEventListener (AccessibleEventListener *listener,
-                              const char              *eventType)
-{
-  Accessibility_Registry_deregisterGlobalEventListener (
-         cspi_registry (),
-         (Accessibility_EventListener) BONOBO_OBJREF (listener),
-         (CORBA_char *) eventType,
-         cspi_ev ());
-
-  return !cspi_exception ();
-}
-
-/**
- * getDesktopCount:
+ * SPI_getDesktopCount:
  *
  * Get the number of virtual desktops.
  * NOTE: currently multiple virtual desktops are not implemented, this
  *       function always returns '1'.
  *
  * Returns: an integer indicating the number of active virtual desktops.
- *
  **/
 int
-getDesktopCount ()
+SPI_getDesktopCount ()
 {
-  return Accessibility_Registry_getDesktopCount (cspi_registry (), cspi_ev ());
+  if (!desktops) SPI_getDesktopList (NULL);
+  if (!desktops) return -1;
+  return desktops->len;
 }
 
 /**
- * getDesktop:
+ * SPI_getDesktop:
  * @i: an integer indicating which of the accessible desktops is to be returned.
  *
  * Get the virtual desktop indicated by index @i.
@@ -172,22 +53,22 @@ getDesktopCount ()
  *       function always returns '1'.
  *
  * Returns: a pointer to the 'i-th' virtual desktop's #Accessible representation.
- *
  **/
 Accessible*
-getDesktop (int i)
+SPI_getDesktop (int i)
 {
-  return cspi_object_add_check (Accessibility_Registry_getDesktop (cspi_registry (),
-                                                                  (CORBA_short) i,
-                                                                  cspi_ev ()));
+  if (!desktops) SPI_getDesktopList (NULL);
+  if (!desktops) return NULL;
+  return cspi_ref_accessible (spi_bus_registry, g_array_index (desktops, char *, i));
 }
 
 /**
- * getDesktopList:
- * @list: a pointer to an array of #Accessible objects.
+ * SPI_getDesktopList:
+ * @desktop_list: a pointer to an array of #Accessible references.
  *
  * Get the list of virtual desktops.  On return, @list will point
- *     to a newly-created array of virtual desktop pointers.
+ *     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.
  *
@@ -198,18 +79,66 @@ getDesktop (int i)
  *          placed in the list pointed to by parameter @list.
  **/
 int
-getDesktopList (Accessible **list)
+SPI_getDesktopList (Accessible ***desktop_list)
+{
+  int i;
+  Accessible **list;
+
+  if (desktop_list) *desktop_list = NULL;
+
+  if (!desktops)
+  {
+    dbind_connection_method_call (cspi_bus(), spi_bus_registry, spi_path_registry, spi_interface_registry, "getDesktopList", NULL, "=>ao", &desktops);
+    if (!desktops) return 0;
+  }
+
+  list = g_new0 (Accessible *, desktops->len + 1);
+
+  if (!desktop_list) return desktops->len;
+  for (i = 0; i < desktops->len; i++)
+    {
+      list [i] = cspi_ref_accessible (spi_bus_registry, g_array_index (desktops, char *, i));
+    }
+  list [i] = NULL;
+
+  *desktop_list = list;
+
+  return i;
+}
+
+/**
+ * SPI_freeDesktopList:
+ * @desktop_list: a pointer to an array of #Accessible objects
+ * as returned from @SPI_getDesktopList
+ * 
+ * This routine frees the memory associated with the list.
+ **/
+void
+SPI_freeDesktopList (Accessible **desktop_list)
 {
-  *list = NULL;
-  return 0;
+  Accessible **p;
+  
+  for (p = desktop_list; p && *p; p++)
+    {
+      cspi_object_unref (*p);
+    }
+  g_free (desktop_list);
 }
 
 /**
- * registerAccessibleKeystrokeListener:
+ * SPI_KEYSET_ALL_KEYS:
+ * @SPI_KEYSET_ALL_KEYS: A special value for an AccessibleKeySet type, which tacitly
+ *                       includes all keycodes and keyvals for the specified modifier set.
+ **/
+
+/**
+ * SPI_registerAccessibleKeystrokeListener:
  * @listener:  a pointer to the #AccessibleKeystrokeListener for which
  *             keystroke events are requested.
  * @keys:      a pointer to the #AccessibleKeySet indicating which
- *             keystroke events are requested, or #CSPI_KEYSET_ALL_KEYS.
+ *             keystroke events are requested, or #SPI_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 event modifiers must be set in combination with @keys,
  *             events will only be reported for key events for which all
@@ -222,89 +151,91 @@ getDesktopList (Accessible **list)
  *             the behavior of the notification/listener transaction.
  *             
  * Register a listener for keystroke events, either pre-emptively for
- *             all windows (CSPI_KEYLISTENER_ALL_WINDOWS), or
- *             non-preemptively (CSPI_KEYLISTENER_NOSYNC).
- *             ( Other sync_type values may be available in the future.)
+ *             all windows (SPI_KEYLISTENER_ALL_WINDOWS),
+ *             non-preemptively (SPI_KEYLISTENER_NOSYNC), or
+ *             pre-emptively at the toolkit level (SPI_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 )
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
  **/
-void
-registerAccessibleKeystrokeListener (AccessibleKeystrokeListener *listener,
-                                    AccessibleKeySet *keys,
-                                    AccessibleKeyMaskType modmask,
-                                    AccessibleKeyEventMask eventmask,
-                                    AccessibleKeyListenerSyncType sync_type)
+SPIBoolean
+SPI_registerAccessibleKeystrokeListener (AccessibleKeystrokeListener  *listener,
+                                        AccessibleKeySet             *keys,
+                                        AccessibleKeyMaskType         modmask,
+                                        AccessibleKeyEventMask        eventmask,
+                                        AccessibleKeyListenerSyncType sync_type)
 {
-  gint                                i, mask;
-  Accessibility_KeySet                key_set;
-  Accessibility_KeyEventTypeSeq       key_events;
+  gchar *path = cspi_device_listener_get_path (listener);
+  gint                                i;
+  GArray *key_set;
+  dbus_uint32_t key_events = 0;
   Accessibility_ControllerEventMask   controller_event_mask;
-  Accessibility_DeviceEventController device_event_controller;
+  Accessibility_EventListenerMode     listener_mode;
+  DBusError error;
+  SPIBoolean                          retval = FALSE;
 
-  device_event_controller = 
-    Accessibility_Registry_getDeviceEventController (cspi_registry (), cspi_ev ());
-
-  g_return_if_fail (cspi_warn_ev (cspi_ev (), "getting event controller"));
+  if (!listener)
+    {
+      return retval;
+    }
 
-  /* copy the keyval filter values from the C api into the CORBA KeySet */
+  /* copy the keyval filter values from the C api into the DBind KeySet */
   if (keys)
     {
-      key_set._length = keys->len;
-      key_set._buffer = Accessibility_KeySet_allocbuf (keys->len);
-      for (i = 0; i < key_set._length; ++i)
+      key_set = g_array_sized_new (FALSE, TRUE, sizeof (Accessibility_KeyDefinition), keys->len);
+      key_set->len = keys->len;
+      for (i = 0; i < keys->len; ++i)
         {
-          /* we overload the keyset long w/keycodes, the - bit acts as a flag */
-          key_set._buffer[i] = (keys->keysyms[i]) ? keys->keysyms[i] :
-                                                -keys->keycodes[i];
-         /* g_print ("key-set %d = %d\n", i, (int) key_set->_buffer[i]); */
+         Accessibility_KeyDefinition *kd =  ((Accessibility_KeyDefinition *) key_set->data) + i;
+          kd->keycode = keys->keycodes[i];
+         kd->keysym = keys->keysyms[i];
+         if (keys->keystrings && keys->keystrings[i])
+           {
+             kd->keystring = keys->keystrings[i];
+           } 
+          else 
+            {
+             kd->keystring = "";
+           }
         }
     }
   else
     {
-      key_set._length = 0;
-      key_set._buffer = NULL;
+      key_set = g_array_sized_new (FALSE, TRUE, sizeof (Accessibility_KeyDefinition), 0);
     }
        
-  /* copy the event filter values from the C api into the CORBA KeyEventTypeSeq */
-  mask = 1;
-  i = 0;
-  do
-    {
-      if (mask & eventmask)
-        {
-          ++i; 
-       }
-      mask <<= 1;
-    }
-  while (mask & 0xFFFF);
-  
-  key_events._buffer = Accessibility_KeyEventTypeSeq_allocbuf (i);
-  i = 0;
+  /* copy the event filter values from the C api into the DBus key_events */
   if (eventmask & SPI_KEY_PRESSED)
     {
-      key_events._buffer[i++] = Accessibility_KEY_PRESSED;
+      key_events |= (1 << Accessibility_KEY_PRESSED_EVENT);
     }
   if (eventmask & SPI_KEY_RELEASED)
     {
-      key_events._buffer[i++] = Accessibility_KEY_RELEASED;
+      key_events |= (1 << Accessibility_KEY_RELEASED_EVENT);
     }
-  key_events._length = i;
   
-  controller_event_mask.value = (CORBA_unsigned_long) modmask;
-  controller_event_mask.refcount = (CORBA_unsigned_short) 1;
-
-  Accessibility_DeviceEventController_registerKeystrokeListener (
-         device_event_controller,
-         BONOBO_OBJREF (listener),
-         &key_set,
-         &controller_event_mask,
-         &key_events,
-         (CORBA_boolean) ((sync_type & SPI_KEYLISTENER_ALL_WINDOWS)!=0),
-         cspi_ev ());
-
-  bonobo_object_release_unref (device_event_controller, cspi_ev ());
+  controller_event_mask = (dbus_uint32_t) modmask;
+
+  listener_mode.synchronous =
+         (dbus_bool_t) ((sync_type & SPI_KEYLISTENER_SYNCHRONOUS)!=0);
+  listener_mode.preemptive =
+         (dbus_bool_t) ((sync_type & SPI_KEYLISTENER_CANCONSUME)!=0);
+  listener_mode.global =
+         (dbus_bool_t) ((sync_type & SPI_KEYLISTENER_ALL_WINDOWS)!=0);
+
+    dbus_error_init (&error);
+    dbind_connection_method_call (cspi_bus(), spi_bus_registry, spi_path_dec, spi_interface_dec, "registerKeystrokeListener", &error, "oa(iisi)uu(bbb)=>b", path, key_set, controller_event_mask, key_set, &listener_mode, &retval);
+
+  g_array_free (key_set, TRUE);
+  g_free (path);
+
+  return retval;
 }
 
 /**
- * deregisterAccessibleKeystrokeListener:
+ * SPI_deregisterAccessibleKeystrokeListener:
  * @listener: a pointer to the #AccessibleKeystrokeListener for which
  *            keystroke events are requested.
  * @modmask:  the key modifier mask for which this listener is to be
@@ -312,46 +243,120 @@ registerAccessibleKeystrokeListener (AccessibleKeystrokeListener *listener,
  *
  * 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.
  **/
-void
-deregisterAccessibleKeystrokeListener (AccessibleKeystrokeListener *listener,
-                                      AccessibleKeyMaskType modmask)
+SPIBoolean
+SPI_deregisterAccessibleKeystrokeListener (AccessibleKeystrokeListener *listener,
+                                          AccessibleKeyMaskType        modmask)
 {
+  gchar *path = cspi_device_listener_get_path (listener);
   Accessibility_ControllerEventMask   controller_event_mask;
-  Accessibility_KeySet                key_set;
-  Accessibility_KeyEventTypeSeq       key_events;
-  Accessibility_DeviceEventController device_event_controller;
+  GArray *key_set;
+  dbus_uint32_t key_events = 0;
+  DBusError error;
+
+  if (!listener)
+    {
+      return FALSE;
+    }
+
+
+  controller_event_mask = (dbus_uint32_t) modmask;
+
+      key_set = g_array_sized_new (FALSE, TRUE, sizeof (Accessibility_KeyDefinition), 0);
+    dbind_connection_method_call (cspi_bus(), spi_bus_registry, spi_path_dec, spi_interface_dec, "deregisterKeystrokeListener", &error, "oa(iisi)uu", path, &key_set, key_events, controller_event_mask);
+  g_free (path);
+  return TRUE;
+}
+
+/**
+ * SPI_registerDeviceEventListener:
+ * @listener:  a pointer to the #AccessibleDeviceListener which requests
+ *             the events.
+ * @eventmask: an #AccessibleDeviceEventMask mask indicating which
+ *             types of key events are requested (#SPI_KEY_PRESSED, etc.).
+ * @filter: Unused parameter.
+ *             
+ * Register a listener for device events, for instance button events.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+SPIBoolean
+SPI_registerDeviceEventListener (AccessibleDeviceListener  *listener,
+                                AccessibleDeviceEventMask  eventmask,
+                                void                      *filter)
+{
+  SPIBoolean                          retval = FALSE;
+  dbus_uint32_t event_types = 0;
+  gint                                i;
+  gchar *path = cspi_device_listener_get_path (listener);
+  DBusError error;
 
-  device_event_controller = 
-    Accessibility_Registry_getDeviceEventController (cspi_registry (), cspi_ev ());
+  if (!listener)
+    {
+      return retval;
+    }
 
-  g_return_if_fail (cspi_warn_ev (cspi_ev (), "getting event controller"));
+  /* copy the event filter values from the C api into the CORBA KeyEventTypeSeq */
+  
+  if (eventmask & SPI_BUTTON_PRESSED)
+    {
+      event_types |= (1 << Accessibility_BUTTON_PRESSED_EVENT);
+    }
+  if (eventmask & SPI_BUTTON_RELEASED)
+    {
+      event_types |= (1 << Accessibility_BUTTON_RELEASED_EVENT);
+    }
 
-  controller_event_mask.value = (CORBA_unsigned_long) modmask;
-  controller_event_mask.refcount = (CORBA_unsigned_short) 1;
+  dbus_error_init (&error);
+    dbind_connection_method_call (cspi_bus(), spi_bus_registry, spi_path_dec, spi_interface_dec, "registerDeviceEventListener", &error, "ou=>b", path, event_types, &retval);
+  g_free (path);
+  return retval;
+}
 
-  key_events._buffer = NULL;
-  key_events._length = 0;
+/**
+ * SPI_deregisterDeviceEventListener:
+ * @listener: a pointer to the #AccessibleDeviceListener for which
+ *            device events are requested.
+ * @filter: Unused parameter.
+ *
+ * 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.
+ **/
+SPIBoolean
+SPI_deregisterDeviceEventListener (AccessibleDeviceListener *listener,
+                                  void                     *filter)
+{
+  dbus_uint32_t event_types = 0;
+  gchar *path = cspi_device_listener_get_path (listener);
+  DBusError error;
 
-  key_set._buffer = NULL;
-  key_set._length = 0;
+  if (!listener)
+    {
+      return FALSE;
+    }
 
-  Accessibility_DeviceEventController_deregisterKeystrokeListener (
-         device_event_controller,
-         BONOBO_OBJREF (listener),
-         &key_set,
-         &controller_event_mask,
-         &key_events,
-         (CORBA_boolean) TRUE,
-         cspi_ev ());
+  event_types |= (1 << Accessibility_BUTTON_PRESSED_EVENT);
+  event_types |= (1 << Accessibility_BUTTON_RELEASED_EVENT);
 
-  bonobo_object_release_unref (device_event_controller, NULL);
+  dbus_error_init (&error);
+    dbind_connection_method_call (cspi_bus(), spi_bus_registry, spi_path_dec, spi_interface_dec, "deregisterDeviceEventListener", &error, "ou", path, event_types);
+  g_free (path);
+  return TRUE;
 }
 
 /**
- * generateKeyEvent:
+ * SPI_generateKeyboardEvent:
  * @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
  *           is to be interpreted as a keysym rather than a keycode
  *           (CSPI_KEYSYM), or whether to synthesize
@@ -360,42 +365,74 @@ deregisterAccessibleKeystrokeListener (AccessibleKeystrokeListener *listener,
  * Synthesize a keyboard event (as if a hardware keyboard event occurred in the
  * current UI context).
  *
+ * Returns: #TRUE if successful, otherwise #FALSE.
  **/
-void
-generateKeyEvent (long int keyval, AccessibleKeySynthType synth_type)
+SPIBoolean
+SPI_generateKeyboardEvent (long int keyval,
+                          char *keystring,
+                          AccessibleKeySynthType synth_type)
 {
-/* TODO: check current modifier status and
- *  send keycode to alter, if necessary
- */
-  Accessibility_DeviceEventController device_event_controller = 
-         Accessibility_Registry_getDeviceEventController (cspi_registry (), cspi_ev ());
+  dbus_uint32_t keysynth_type;
+  dbus_int32_t keycode = keyval;
+  DBusError error;
 
-  g_return_if_fail (cspi_warn_ev (cspi_ev (), "getting event controller"));
+  switch (synth_type)
+    {
+      case SPI_KEY_PRESS:
+         keysynth_type = Accessibility_KEY_PRESS;
+         break;
+      case SPI_KEY_RELEASE:
+         keysynth_type = Accessibility_KEY_RELEASE;
+         break;
+      case SPI_KEY_PRESSRELEASE:
+         keysynth_type = Accessibility_KEY_PRESSRELEASE;
+         break;
+      case SPI_KEY_SYM:
+         keysynth_type = Accessibility_KEY_SYM;
+         break;
+      case SPI_KEY_STRING:
+         keysynth_type = Accessibility_KEY_STRING;
+         break;
+      default:
+          return FALSE;
+    }
 
-  Accessibility_DeviceEventController_generateKeyEvent (device_event_controller,
-                                                       keyval,
-                                                       (unsigned long) synth_type,
-                                                       cspi_ev ());
+  if (!keystring) keystring = "";
+  dbus_error_init (&error);
+    dbind_connection_method_call (cspi_bus(), spi_bus_registry, spi_path_dec, spi_interface_dec, "generateKeyboardEvent", &error, "isu", keycode, keystring, keysynth_type);
 
-  bonobo_object_release_unref (device_event_controller, NULL);
+  return TRUE;
 }
 
 /**
- * generateMouseEvent:
+ * SPI_generateMouseEvent:
  * @x: a #long indicating the screen x coordinate of the mouse event.
  * @y: a #long indicating the screen y coordinate of the mouse event.
  * @name: a string indicating which mouse event to be synthesized
- *        (e.g. "button1", "button2", "mousemove").
+ *        (e.g. "b1p", "b1c", "b2r", "rel", "abs").
  *
  * Synthesize 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.
- * Not Yet Implemented.
+ * 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.
  **/
-void
-generateMouseEvent (long x, long y, char *name)
+SPIBoolean
+SPI_generateMouseEvent (long x, long y, char *name)
 {
-  ;
+  dbus_int32_t dbus_x = x, dbus__y = y;
+  DBusError error;
+
+  dbus_error_init (&error);
+    dbind_connection_method_call (cspi_bus(), spi_bus_registry, spi_path_dec, spi_interface_dec, "generateMouseEvent", &error, "iis", x, y, name);
+  return TRUE;
 }
 
+char *
+cspi_device_listener_get_path (CSpiDeviceListener *listener)
+{
+  return g_strdup_printf ("/org/freedesktop/atspi/listeners/%d", listener->id);
+}