-
/*
+ * AT-SPI - Assistive Technology Service Provider Interface
+ * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
+ *
+ * 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
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
*
- * Global functions serviced by the registry
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
*
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
*/
-/* static stuff used only by registry C bindings */
-static GList *key_listeners = NULL;
-static Display *display = NULL;
+/* spi_registry.c: Global functions wrapping the registry */
-/**
- * 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 "Focus", "Window", "Mouse",
- * and toolkit events (e.g. "Gtk", "AWT").
- * Examples: "focus:", "Gtk:GtkWidget:button_press_event".
- *
- * 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.
- *
- **/
-boolean
-registerGlobalEventListener (AccessibleEventListener *listener,
- char *eventType)
-{
- Accessibility_Registry_registerGlobalEventListener (
- registry,
- (Accessibility_EventListener)
- bonobo_object_corba_objref (bonobo_object (listener)),
- eventType,
- &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION)
- {
- return FALSE;
- }
- else
- {
- return TRUE;
- }
-}
+#include <cspi/spi-private.h>
-/**
- * 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.
- *
- * Returns: #TRUE if successful, otherwise #FALSE.
- *
- **/
-boolean
-deregisterGlobalEventListenerAll (AccessibleEventListener *listener)
-{
- Accessibility_Registry_deregisterGlobalEventListenerAll (
- registry,
- (Accessibility_EventListener)
- CORBA_Object_duplicate (
- bonobo_object_corba_objref (
- bonobo_object (listener)), &ev),
- &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION)
- {
- return FALSE;
- }
- else
- {
- return TRUE;
- }
-}
-/**
- * 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.
- *
- **/
-boolean
-deregisterGlobalEventListener (AccessibleEventListener *listener,
- char *eventType)
-{
- Accessibility_Registry_deregisterGlobalEventListener (
- registry,
- (Accessibility_EventListener)
- CORBA_Object_duplicate (
- bonobo_object_corba_objref (bonobo_object (listener)), &ev),
- (CORBA_char *) eventType,
- &ev);
-
- if (ev._major != CORBA_NO_EXCEPTION)
- {
- return FALSE;
- }
- else
- {
- return TRUE;
- }
-}
+static GArray *desktops;
/**
- * 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 (registry, &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.
* 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 Obj_Add (Accessibility_Registry_getDesktop (registry, (CORBA_short) i, &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.
*
* placed in the list pointed to by parameter @list.
**/
int
-getDesktopList (Accessible **list)
+SPI_getDesktopList (Accessible ***desktop_list)
{
- *list = NULL;
- return 0;
+ 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;
}
-static gboolean
-key_event_source_func (void *p)
+/**
+ * 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)
{
- GList *listeners = (GList *)p;
- XEvent *x_event = g_new0 (XEvent, 1);
- while (XPending (display))
+ Accessible **p;
+
+ for (p = desktop_list; p && *p; p++)
{
- XNextEvent (display, x_event);
- while (listeners)
- {
- /* if the listener mask matches, notify it*/
- if (1)
- {
- ;
- }
- }
+ cspi_object_unref (*p);
}
- return TRUE;
+ 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 #SPI_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
* the behavior of the notification/listener transaction.
*
* Register a listener for keystroke events, either pre-emptively for
- * all windows (SPI_KEYLISTENER_ALL_WINDOWS), or
- * non-preemptively (SPI_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)
{
- Accessibility_ControllerEventMask *controller_event_mask =
- Accessibility_ControllerEventMask__alloc();
- Accessibility_DeviceEventController device_event_controller =
- Accessibility_Registry_getDeviceEventController (registry, &ev);
- Accessibility_KeySet *all_keys = Accessibility_KeySet__alloc();
- Accessibility_KeyEventTypeSeq *key_events = Accessibility_KeyEventTypeSeq__alloc();
- Accessibility_KeystrokeListener spi_listener_corba_ref;
- Accessibility_DeviceEventController_ref (device_event_controller, &ev);
- controller_event_mask->value = (CORBA_unsigned_long) modmask;
- controller_event_mask->refcount = (CORBA_unsigned_short) 1;
-
- spi_listener_corba_ref = (Accessibility_KeystrokeListener)
- CORBA_Object_duplicate (bonobo_object_corba_objref (bonobo_object (listener)), &ev);
+ 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_EventListenerMode listener_mode;
+ DBusError error;
+ SPIBoolean retval = FALSE;
+
+ if (!listener)
+ {
+ return retval;
+ }
+
+ /* copy the keyval filter values from the C api into the DBind KeySet */
+ if (keys)
+ {
+ 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)
+ {
+ 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 = g_array_sized_new (FALSE, TRUE, sizeof (Accessibility_KeyDefinition), 0);
+ }
+
+ /* copy the event filter values from the C api into the DBus key_events */
+ if (eventmask & SPI_KEY_PRESSED)
+ {
+ key_events |= (1 << Accessibility_KEY_PRESSED_EVENT);
+ }
+ if (eventmask & SPI_KEY_RELEASED)
+ {
+ key_events |= (1 << Accessibility_KEY_RELEASED_EVENT);
+ }
- Accessibility_DeviceEventController_registerKeystrokeListener (
- device_event_controller,
- spi_listener_corba_ref,
- all_keys,
- controller_event_mask,
- key_events,
- (CORBA_boolean) ((sync_type | SPI_KEYLISTENER_ALL_WINDOWS)!=0),
- &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, key_events, controller_event_mask, &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
* 'deregistered' (of type #AccessibleeyMaskType).
*
+ * 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;
+ 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)
{
- Accessibility_ControllerEventMask *controller_event_mask =
- Accessibility_ControllerEventMask__alloc();
- Accessibility_DeviceEventController device_event_controller =
- Accessibility_Registry_getDeviceEventController (registry, &ev);
- Accessibility_KeySet *all_keys = Accessibility_KeySet__alloc();
- Accessibility_KeyEventTypeSeq *key_events = Accessibility_KeyEventTypeSeq__alloc();
- Accessibility_KeystrokeListener spi_listener_corba_ref;
- Accessibility_DeviceEventController_unref (device_event_controller, &ev);
- controller_event_mask->value = (CORBA_unsigned_long) modmask;
- controller_event_mask->refcount = (CORBA_unsigned_short) 1;
-
- spi_listener_corba_ref = (Accessibility_KeystrokeListener)
- CORBA_Object_duplicate (bonobo_object_corba_objref (bonobo_object (listener)), &ev);
+ SPIBoolean retval = FALSE;
+ dbus_uint32_t event_types = 0;
+ gint i;
+ gchar *path = cspi_device_listener_get_path (listener);
+ DBusError error;
+
+ if (!listener)
+ {
+ return retval;
+ }
+
+ /* copy the event filter values from the C api into the CORBA KeyEventTypeSeq */
- Accessibility_DeviceEventController_deregisterKeystrokeListener (
- device_event_controller,
- spi_listener_corba_ref,
- all_keys,
- controller_event_mask,
- key_events,
- (CORBA_boolean) TRUE,
- &ev);
+ if (eventmask & SPI_BUTTON_PRESSED)
+ {
+ event_types |= (1 << Accessibility_BUTTON_PRESSED_EVENT);
+ }
+ if (eventmask & SPI_BUTTON_RELEASED)
+ {
+ event_types |= (1 << Accessibility_BUTTON_RELEASED_EVENT);
+ }
+
+ 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;
}
/**
- * generateKeyEvent:
+ * 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;
+
+ if (!listener)
+ {
+ return FALSE;
+ }
+
+ event_types |= (1 << Accessibility_BUTTON_PRESSED_EVENT);
+ event_types |= (1 << Accessibility_BUTTON_RELEASED_EVENT);
+
+ 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;
+}
+
+/**
+ * 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
- * (SPI_KEYSYM), or whether to synthesize
+ * (CSPI_KEYSYM), or whether to synthesize
* SPI_KEY_PRESS, SPI_KEY_RELEASE, or both (SPI_KEY_PRESSRELEASE).
*
* 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 (registry, &ev);
- Accessibility_DeviceEventController_generateKeyEvent (device_event_controller,
- keyval,
- (unsigned long) synth_type,
- &ev);
+ dbus_uint32_t keysynth_type;
+ dbus_int32_t keycode = keyval;
+ DBusError error;
+
+ 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;
+ }
+
+ 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);
+
+ 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);
+}