[g-a-devel]at-spi patch for device events



Hi:

Attached is a patch that adds some new functionality by exposing/tidying
some existing internals for dealing with "device events". There is still
a special listener mechanism for key events, which are rather different
from others, but in order to fix some very nasty blockers for GOK is is
necessary for listeners to mouse events to be able to consume those
events.  Perhaps a refactor could have extended the key listener API to
do this, but not without breaking API and bincompat; so new API has been
added:

SPI_createAccessibleDeviceListener (AccessibleDeviceListenerCB cb, 
					void * user_data); AccessibleDeviceListener_addCallback
(AccessibleDeviceListener l,
					AccessibleDeviceListenerCB cb);
AccessibleDeviceListener_removeCallback (AccessibleDeviceListener l,
					AccessibleDeviceListenerCB cb);
AccessibleDeviceListener_unref (AccessibleDeviceListener l),

Also AccessibleKeystroke and AccessibleDeviceEvent are made more
explicitly equivalent.

The IDL for DeviceEventController has been slightly expanded to support
these new listeners as well.

Bin and API compatibility for our clients has been preserved to the best
of my knowledge.

This functionality is essential to GOK and important to other at-spi
clients.

comments?  Apologies for the size of the patch, there was lots of
reworking to do inside deviceeventcontroller.c.

I plan to commit this weekend if there are no unresolved issues.

thanks!

-Bill



? 1
? at-spi-1.2.0.tar.gz
? at-spi-big-patch.diff
? at-spi-dec-patch.diff
? at-spi-patch-for-ut.diff
? autom4te.cache
? device-event-patch.diff
? latest.diff
? make.log
? docs/reference/cspi/tmpl/at-spi-cspi-unused.sgml
? docs/reference/cspi/tmpl/spi_streamable_content.sgml
? test/core.1594
? test/core.28098
? test/core.746
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/at-spi/ChangeLog,v
retrieving revision 1.254
diff -u -r1.254 ChangeLog
--- ChangeLog	23 Oct 2002 15:57:39 -0000	1.254
+++ ChangeLog	14 Nov 2002 22:06:44 -0000
@@ -1,3 +1,149 @@
+2002-11-14  Bill Haneman <bill haneman sun com>
+
+	* idl/Accessibility_Registry.idl:
+	(KeyEventType, EventType):
+	Marked KeyEventType as deprecated; it duplicates
+	functionality of EventType, which has been extended to
+	include Mouse-button events.
+	(KeyEventTypeSeq): defined in terms of EventType.
+	(registerDeviceEventListener, deregisterDeviceEventListener):
+	New methods, for managing listeners to device events,
+	which potentially may consume them.	
+	
+	* cspi/spi-impl.h:
+	Added definition for AccessibleDeviceListener.
+
+	* cspi/spi-listener.h:
+	(enum AccessibleDeviceEventType):
+	Added SPI_BUTTON_PRESSED and SPI_BUTTON_RELEASED.
+	Typedef'd AccessibleKeyEventType to AccessibleDeviceEventType
+	for backwards compat.
+	(AccessibleKeystroke): Renamed AccessibleKeystroke to AccessibleDeviceEvent,
+	and typedef'd AccessibleKeystroke to it for back-compat.
+	(AccessibleDeviceListenerCB):
+	New function prototype typedef.
+
+	* cspi/spi.h:
+	(AccessibleDeviceEventMask): New typedef.
+	(AccessibleModifierMaskType): New typedef (renamed from AccessibleKeyMaskType).
+	(AccessibleKeyMaskType): 
+	Set equivalent to AccessibleModifierMaskType for back-compat.	
+	(SPI_createAccessibleKeystrokeListener):
+	(AccessibleKeystrokeListener_unref):
+	Deprecated in favor of equivalent (better-named) new API below..
+	keystroke listeners are like all device listeners.
+	(SPI_createAccessibleDeviceListener, AccessibleDeviceListener_unref)
+	New API names for old features :-).
+	(AccessibleDeviceListener_addCallback):
+	(AccessibleDeviceListener_removeCallback): 
+	(SPI_registerDeviceEventListener): 
+	(SPI_deregisterDeviceEventListener): 
+	New methods.
+	
+	* cspi/spi_event.c:
+	(SPI_createAccessibleKeystrokeListener):
+	Use new preferred API, cspi_device_listener_new() and
+	cspi_device_listener_add_cb().
+	(AccessibleKeystrokeListener_removeCallback):
+	Use new preferred API, cspi_device_listener_remove_cb().
+	(AccessibleKeystrokeListener_unref):
+	Use new preferred API, cspi_device_listener_unref().
+	(SPI_createAccessibleDeviceListener):
+	(AccessibleDeviceListener_addCallback):
+	(AccessibleDeviceListener_removeCallback):
+	Implementation of new API.
+
+	* cspi/spi_registry.c:
+	(SPI_registerDeviceEventListener):
+	(SPI_deregisterDeviceEventListener):
+	Implementation of new API.
+
+	* cspi/bonobo/cspi-bonobo-listener.c:
+	(EventHandler):
+	Changed union (bin-and-api-compatibly) to refer to AccessibleDeviceListenerCB.
+	(cspi_key_event): renamed to cspi_device_event().
+	Internal use of CSpiKeystrokeListener changed to CSpiDeviceListener.
+	Extended to handle mouse button events as well as key events.
+	(CSpiKeystrokeListener):
+	Class superceded by CSpiDeviceListener.
+	(cspi_keystroke_listener_add_callback, cspi_keystroke_listener_get_corba):
+	These internal APIs changed to "*device_listener" from "*keystroke_listener".
+
+	* cspi/bonobo/cspi-bonobo-listener.h:
+	(CSpiKeystrokeListener):
+	Class superceded by CSpiDeviceListener.
+	(cspi_keystroke_listener_add_callback, cspi_keystroke_listener_get_corba):
+	These internal APIs changed to "*device_listener" from "*keystroke_listener".
+
+	* libspi/Makefile.am:
+	Replaced keystrokelistener.h and keystrokelistener.c
+	with devicelistener.h and devicelistener.c; keystrokelisener.h
+	stub retained for back-compat.
+
+	* libspi/keystrokelistener.c:
+	Removed file.
+
+	* libspi/libspi.h:
+	Replaced inclusion of keystrokelistener.h with devicelistener.h.	
+
+	* registryd/deviceeventcontroller.c:
+	(DEControllerListener): Added Accessibility_EventTypeSeq member.
+	(DEControllerKeyListener): Removed Accessibility_KeyEventTypeSeq member.
+	(DEControllerPrivateData): Added xkb settings data.
+	(spi_dec_poll_mouse_moved): Changed to dispatch device events for
+	button release events (which can't be captured via XGrabButton).
+	Don't dispatch via the 'normal' event mechanism if the device event was
+	consumed.
+	(spi_dec_key_listener_new, spi_key_listener_clone, spi_key_listener_data_free):
+	Handle the typeseq data in its new location (see above).
+	(spi_dec_listener_new, spi_listener_clone, spi_listener_clone_free):
+	New methods, for "generic" device listeners.
+	(spi_controller_register_device_listener):
+	Now handle mouse event listeners as well as key listeners.
+	(spi_controller_notify_mouselisteners):
+	New internal method.
+	(spi_device_event_controller_forward_mouse_event):
+	Now we notify mouse device listeners as well as generating the
+	non-consumable "mouse:" events.  
+	(global_filter_fn):
+	We must check and restore the XKB
+	modifier map if we consume the event, since the act of triggering
+	a mouse event will normally reset the XKB latch.  This is required for 
+	instance by GOK.
+	(spi_controller_register_with_devices):
+	Load the XKB settings when registering, and register for XKB 
+	state notify events. 
+	(spi_key_eventtype_seq_contains_event):
+	Renamed spi_eventtype_seq_contains_event, since it's used
+	internally for all device event types now.
+	(spi_key_event_matches_listener):
+	Uses spi_eventtype_seq_contains_event now.
+	(spi_device_event_controller_object_finalize):
+	Free the private data and the XkbKeyboard struct.
+	(impl_register_device_listener, impl_deregister_device_listener):
+	Implementation of new IDL.
+	(spi_deregister_controller_device_listener):
+	New internal method.
+	(dec_xkb_get_slowkeys_delay dec_xkb_get_bouncekeys_delay):
+	More efficient implementation, we don't have to create a new
+	XkbControls structure every time we query.
+	(spi_device_event_controller_class_init):
+	Initialize the epv entries for the new IDL.  Assign the 
+	"spi-dec-private" quark.
+	(spi_device_event_controller_init):
+	Initialize the private data.
+	(spi_device_event_controller_forward_key_event):
+	Removed a bogus CORBA_exception_free() call.
+	
+	* registryd/deviceeventcontroller.h:
+	Replaced inclusion of keystrokelistener.h with
+	devicelistener.h.
+
+	* test/event-listener-test.c:
+	
+	
+	
+
 2002-10-23  Vitaly Tishkov  <tvv sparc spb su>
 
 	* registryd/deviceeventcontroller.c
Index: configure.in
===================================================================
RCS file: /cvs/gnome/at-spi/configure.in,v
retrieving revision 1.52
diff -u -r1.52 configure.in
--- configure.in	21 Oct 2002 19:41:43 -0000	1.52
+++ configure.in	14 Nov 2002 22:06:44 -0000
@@ -1,10 +1,10 @@
 AC_INIT(idl/Accessibility.idl)
 
 AT_SPI_MAJOR_VERSION=1
-AT_SPI_MINOR_VERSION=1
-AT_SPI_MICRO_VERSION=2
-AT_SPI_INTERFACE_AGE=2
-AT_SPI_BINARY_AGE=2
+AT_SPI_MINOR_VERSION=2
+AT_SPI_MICRO_VERSION=0
+AT_SPI_INTERFACE_AGE=0
+AT_SPI_BINARY_AGE=0
 AT_SPI_VERSION="$AT_SPI_MAJOR_VERSION.$AT_SPI_MINOR_VERSION.$AT_SPI_MICRO_VERSION"
 AM_INIT_AUTOMAKE(at-spi, $AT_SPI_VERSION)
 AC_SUBST(AT_SPI_MAJOR_VERSION)
Index: atk-bridge/bridge.c
===================================================================
RCS file: /cvs/gnome/at-spi/atk-bridge/bridge.c,v
retrieving revision 1.46
diff -u -r1.46 bridge.c
--- atk-bridge/bridge.c	13 Sep 2002 13:08:57 -0000	1.46
+++ atk-bridge/bridge.c	14 Nov 2002 22:06:45 -0000
@@ -73,6 +73,7 @@
 extern void gnome_accessibility_module_shutdown (void);
 
 static int     atk_bridge_initialized = FALSE;
+static int     atk_bridge_registered = FALSE;
 static guint   atk_bridge_focus_tracker_id = 0;
 static guint   atk_bridge_key_event_listener_id = 0;
 static GArray *listener_ids = NULL;
@@ -84,10 +85,45 @@
 extern void gnome_accessibility_module_init     (void);
 extern void gnome_accessibility_module_shutdown (void);
 
+static void
+spi_atk_bridge_activate_and_register (void) 
+{
+  if (spi_atk_bridge_get_registry () == CORBA_OBJECT_NIL)
+    {
+      g_error ("Could not locate registry");
+    }
+
+  bonobo_activate ();
+
+  /* Create the accessible application server object */
+
+  this_app = spi_application_new (atk_get_root ());
+
+  fprintf (stderr, "About to register application\n");
+
+  spi_atk_bridge_register_application (spi_atk_bridge_get_registry ());
+  
+  g_atexit (spi_atk_bridge_exit_func);
+
+  fprintf (stderr, "Application registered & listening\n");
+}
+
+static gboolean 
+spi_atk_bridge_toplevel_listener (GSignalInvocationHint *ihint,
+				  guint                  n_param_values,
+				  const GValue          *param_values,
+				  gpointer               data)
+{
+
+  if (!atk_bridge_registered) 
+    spi_atk_bridge_activate_and_register ();
+
+  return TRUE;
+}
+
 static int
 atk_bridge_init (gint *argc, gchar **argv[])
 {
-  CORBA_Environment ev;
 
   if (atk_bridge_initialized)
     {
@@ -105,30 +141,22 @@
    * applications, we detect bonobo components by seeing
    * if they were activated with the intention of extracting
    * an impl. by IID - very solid.
+   * However, if this app launches another toplevel window, 
+   * we need to register (belatedly), otherwise the toplevel will be
+   * "orphaned" since it's not embedded.
    */
-  if (bonobo_activation_iid_get ())
-	  return 0;
-
-  CORBA_exception_init(&ev);
-
-  if (spi_atk_bridge_get_registry () == CORBA_OBJECT_NIL)
+  if (bonobo_activation_iid_get ()) 
     {
-      g_error ("Could not locate registry");
+      /* add this at idle, otherwise the gtk+ window type might 
+       * not be initialized yet, and we don't want to introduce a hard
+       * gtk+ dependency on the atk bridge. 
+       */
+      atk_add_global_event_listener (spi_atk_bridge_toplevel_listener,
+				     "window:create");
+      return 0;
     }
 
-  bonobo_activate ();
-
-  /* Create the accessible application server object */
-
-  this_app = spi_application_new (atk_get_root ());
-
-  fprintf (stderr, "About to register application\n");
-
-  spi_atk_bridge_register_application (spi_atk_bridge_get_registry ());
-  
-  g_atexit (spi_atk_bridge_exit_func);
-
-  fprintf (stderr, "Application registered & listening\n");
+  spi_atk_bridge_activate_and_register ();
 
   return 0;
 }
@@ -140,6 +168,7 @@
                                               BONOBO_OBJREF (this_app),
                                               &ev);
   spi_atk_register_event_listeners ();
+  atk_bridge_registered = TRUE;
 }
 
 static Accessibility_Registry
@@ -244,12 +273,7 @@
   add_signal_listener ("Gtk:AtkTable:column-reordered");
   add_signal_listener ("Gtk:AtkTable:column-deleted");
   add_signal_listener ("Gtk:AtkTable:model-changed");
-/*
- * May add the following listeners to implement preemptive key listening for GTK+
- *
- * atk_add_global_event_listener (spi_atk_bridge_widgetkey_listener, "Gtk:GtkWidget:key-press-event");
- * atk_add_global_event_listener (spi_atk_bridge_widgetkey_listener, "Gtk:GtkWidget:key-release-event");
- */
+
   atk_bridge_key_event_listener_id = atk_add_key_event_listener (
     spi_atk_bridge_key_listener, NULL);
   
Index: cspi/spi-impl.h
===================================================================
RCS file: /cvs/gnome/at-spi/cspi/spi-impl.h,v
retrieving revision 1.15
diff -u -r1.15 spi-impl.h
--- cspi/spi-impl.h	13 Sep 2002 13:08:58 -0000	1.15
+++ cspi/spi-impl.h	14 Nov 2002 22:06:45 -0000
@@ -52,6 +52,7 @@
 
 typedef void AccessibleEventListener;
 typedef void AccessibleKeystrokeListener;
+typedef void AccessibleDeviceListener;
 
 typedef unsigned int SPIBoolean;
 
Index: cspi/spi-listener.h
===================================================================
RCS file: /cvs/gnome/at-spi/cspi/spi-listener.h,v
retrieving revision 1.18
diff -u -r1.18 spi-listener.h
--- cspi/spi-listener.h	13 Sep 2002 13:08:58 -0000	1.18
+++ cspi/spi-listener.h	14 Nov 2002 22:06:45 -0000
@@ -42,19 +42,24 @@
 
 typedef enum {
   SPI_KEY_PRESSED  = 1<<0,
-  SPI_KEY_RELEASED = 1<<1
-} AccessibleKeyEventType;
+  SPI_KEY_RELEASED = 1<<1,
+  SPI_BUTTON_PRESSED = 1<<2,
+  SPI_BUTTON_RELEASED = 1<<3
+} AccessibleDeviceEventType;
 
+typedef AccessibleDeviceEventType AccessibleKeyEventType;
 
 typedef struct {
   long                   keyID;
   short                  keycode;
   char *                 keystring;
   long                   timestamp;
-  AccessibleKeyEventType type;
+  AccessibleDeviceEventType type;
   unsigned short         modifiers;
   SPIBoolean             is_text;	
-} AccessibleKeystroke;
+} AccessibleDeviceEvent;
+
+typedef AccessibleDeviceEvent AccessibleKeystroke;
 
 /*
  * Function prototype typedefs for Event Listener Callbacks.
@@ -68,6 +73,8 @@
 typedef void       (*AccessibleEventListenerCB)     (const AccessibleEvent     *event,
 						     void                      *user_data);
 typedef SPIBoolean (*AccessibleKeystrokeListenerCB) (const AccessibleKeystroke *stroke,
+						     void                      *user_data);
+typedef SPIBoolean (*AccessibleDeviceListenerCB)    (const AccessibleDeviceEvent *stroke,
 						     void                      *user_data);
 
 #ifdef  __cplusplus
Index: cspi/spi.h
===================================================================
RCS file: /cvs/gnome/at-spi/cspi/spi.h,v
retrieving revision 1.49
diff -u -r1.49 spi.h
--- cspi/spi.h	13 Sep 2002 13:08:58 -0000	1.49
+++ cspi/spi.h	14 Nov 2002 22:06:46 -0000
@@ -100,6 +100,7 @@
 } AccessibleKeyListenerSyncType;
 
 typedef unsigned long AccessibleKeyEventMask;
+typedef unsigned long AccessibleDeviceEventMask;
 
 /**
  * AccessibleComponentLayer:
@@ -155,8 +156,8 @@
  **/
 #define SPI_KEYSET_ALL_KEYS NULL
 
-typedef unsigned long AccessibleKeyMaskType;
-
+typedef unsigned long AccessibleModifierMaskType;
+typedef AccessibleModifierMaskType AccessibleKeyMaskType;
 
 /* Basic SPI initialization and event loop function prototypes */
 
@@ -189,7 +190,9 @@
 void                      AccessibleEventListener_unref (
 	                                           AccessibleEventListener  *listener);
 
-/* Keystroke Listener creation and support.  */
+/* Device Event Listener creation and support.  */
+
+/* First four are deprecated in favor of the last four; really just a re-name */
 
 AccessibleKeystrokeListener * SPI_createAccessibleKeystrokeListener (
 	                                AccessibleKeystrokeListenerCB callback,
@@ -204,6 +207,19 @@
 void                          AccessibleKeystrokeListener_unref (
 	                                AccessibleKeystrokeListener *listener);
 
+AccessibleDeviceListener   * SPI_createAccessibleDeviceListener (
+	                                AccessibleDeviceListenerCB callback,
+					void                      *user_data);
+SPIBoolean                    AccessibleDeviceListener_addCallback (
+	                                AccessibleDeviceListener  *listener,
+					AccessibleDeviceListenerCB callback,
+					void                      *user_data);
+SPIBoolean                    AccessibleDeviceListener_removeCallback (
+	                                AccessibleDeviceListener  *listener,
+					AccessibleDeviceListenerCB callback);
+void                          AccessibleDeviceListener_unref (
+	                                AccessibleDeviceListener *listener);
+
 /* Global functions serviced by the registry */
 
 SPIBoolean SPI_registerGlobalEventListener           (
@@ -223,6 +239,12 @@
 SPIBoolean SPI_deregisterAccessibleKeystrokeListener (
 	                               AccessibleKeystrokeListener *listener,
 				       AccessibleKeyMaskType        modmask);
+
+SPIBoolean SPI_registerDeviceEventListener   (
+                                       AccessibleDeviceListener   *listener,
+				       AccessibleDeviceEventMask   eventmask);
+SPIBoolean SPI_deregisterDeviceEventListener (
+				       AccessibleDeviceListener   *listener);
 
 int         SPI_getDesktopCount                  (void);
 Accessible *SPI_getDesktop                       (int i);
Index: cspi/spi_event.c
===================================================================
RCS file: /cvs/gnome/at-spi/cspi/spi_event.c,v
retrieving revision 1.20
diff -u -r1.20 spi_event.c
--- cspi/spi_event.c	13 Sep 2002 13:08:58 -0000	1.20
+++ cspi/spi_event.c	14 Nov 2002 22:06:46 -0000
@@ -198,7 +198,7 @@
 SPI_createAccessibleKeystrokeListener (AccessibleKeystrokeListenerCB callback,
 				       void                         *user_data)
 {
-  AccessibleKeystrokeListener *listener = cspi_keystroke_listener_new ();
+  AccessibleKeystrokeListener *listener = cspi_device_listener_new ();
   if (callback)
     {
       AccessibleKeystrokeListener_addCallback (listener, callback, user_data);
@@ -222,7 +222,7 @@
 					 AccessibleKeystrokeListenerCB callback,
 					 void                         *user_data)
 {
-  cspi_keystroke_listener_add_cb (listener, callback, user_data);
+  cspi_device_listener_add_cb (listener, callback, user_data);
   return TRUE;
 }
 
@@ -240,7 +240,7 @@
 AccessibleKeystrokeListener_removeCallback (AccessibleKeystrokeListener *listener,
 					    AccessibleKeystrokeListenerCB callback)
 {
-  cspi_keystroke_listener_remove_cb (listener, callback);
+  cspi_device_listener_remove_cb (listener, callback);
   return TRUE;
 }
 
@@ -253,5 +253,77 @@
 void
 AccessibleKeystrokeListener_unref (AccessibleKeystrokeListener *listener)
 {
-  cspi_keystroke_listener_unref (listener);
+  cspi_device_listener_unref (listener);
+}
+
+/**
+ * SPI_createAccessibleDeviceListener:
+ * @callback : an #AccessibleDeviceListenerCB callback function, or NULL.
+ * @user_data: a pointer to data which will be passed to the callback when invoked.
+ *
+ * Create a new #AccessibleDeviceListener with a specified callback function.
+ *
+ * Returns: a pointer to a newly-created #AccessibleDeviceListener.
+ *
+ **/
+AccessibleDeviceListener *
+SPI_createAccessibleDeviceListener (AccessibleDeviceListenerCB callback,
+				       void                         *user_data)
+{
+  AccessibleDeviceListener *listener = cspi_device_listener_new ();
+  if (callback)
+    {
+      AccessibleDeviceListener_addCallback (listener, callback, user_data);
+    }
+  return listener;
+}
+
+/**
+ * AccessibleDeviceListener_addCallback:
+ * @listener: the #AccessibleDeviceListener instance to modify.
+ * @callback: an #AccessibleDeviceListenerCB function pointer.
+ * @user_data: a pointer to data which will be passed to the callback when invoked.
+ *
+ * Add an in-process callback function to an existing #AccessibleDeviceListener.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ *
+ **/
+SPIBoolean
+AccessibleDeviceListener_addCallback (AccessibleDeviceListener *listener,
+					 AccessibleDeviceListenerCB callback,
+					 void                         *user_data)
+{
+  cspi_device_listener_add_cb (listener, callback, user_data);
+  return TRUE;
+}
+
+/**
+ * AccessibleDeviceListener_removeCallback:
+ * @listener: the #AccessibleDeviceListener instance to modify.
+ * @callback: an #AccessibleDeviceListenerCB function pointer.
+ *
+ * Remove an in-process callback function from an existing #AccessibleDeviceListener.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ *
+ **/
+SPIBoolean
+AccessibleDeviceListener_removeCallback (AccessibleDeviceListener *listener,
+					    AccessibleDeviceListenerCB callback)
+{
+  cspi_device_listener_remove_cb (listener, callback);
+  return TRUE;
+}
+
+/**
+ * AccessibleDeviceListener_unref:
+ * @listener: a pointer to the #AccessibleDeviceListener being operated on.
+ *
+ * Decrements an #AccessibleDeviceListener's reference count.
+ **/
+void
+AccessibleDeviceListener_unref (AccessibleDeviceListener *listener)
+{
+  cspi_device_listener_unref (listener);
 }
Index: cspi/spi_registry.c
===================================================================
RCS file: /cvs/gnome/at-spi/cspi/spi_registry.c,v
retrieving revision 1.41
diff -u -r1.41 spi_registry.c
--- cspi/spi_registry.c	13 Sep 2002 13:08:58 -0000	1.41
+++ cspi/spi_registry.c	14 Nov 2002 22:06:46 -0000
@@ -477,6 +477,119 @@
 }
 
 /**
+ * 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.).
+ *             
+ * Register a listener for device events, for instance button events.
+ *
+ * Returns: #TRUE if successful, otherwise #FALSE.
+ **/
+SPIBoolean
+SPI_registerDeviceEventListener (AccessibleDeviceListener  *listener,
+				 AccessibleDeviceEventMask  eventmask)
+{
+  Accessibility_DeviceEventController device_event_controller;
+  SPIBoolean                          retval = FALSE;
+  Accessibility_EventTypeSeq          event_types;
+  gint                                i, mask;
+
+  if (!listener)
+    {
+      return retval;
+    }
+
+  device_event_controller = 
+    Accessibility_Registry_getDeviceEventController (cspi_registry (), cspi_ev ());
+
+  cspi_return_val_if_ev ("getting event controller", FALSE);
+
+  /* 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);
+  
+  event_types._buffer = Accessibility_KeyEventTypeSeq_allocbuf (i);
+  i = 0;
+
+  if (eventmask & SPI_BUTTON_PRESSED)
+    {
+      event_types._buffer[i++] = Accessibility_BUTTON_PRESSED_EVENT;
+    }
+  if (eventmask & SPI_BUTTON_RELEASED)
+    {
+      event_types._buffer[i++] = Accessibility_BUTTON_RELEASED_EVENT;
+    }
+
+  event_types._length = i;
+  
+  retval = Accessibility_DeviceEventController_registerDeviceEventListener (
+    device_event_controller,
+    cspi_event_listener_get_corba (listener),
+    &event_types,
+    cspi_ev ());
+
+  cspi_return_val_if_ev ("registering keystroke listener", FALSE);
+
+  cspi_release_unref (device_event_controller);
+
+  return retval;
+}
+
+/**
+ * SPI_deregisterDeviceEventListener:
+ * @listener: a pointer to the #AccessibleDeviceListener for which
+ *            device events are requested.
+ *
+ * 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)
+{
+  Accessibility_ControllerEventMask   controller_event_mask;
+  Accessibility_DeviceEventController device_event_controller;
+  Accessibility_EventTypeSeq       event_types;
+
+  if (!listener)
+    {
+      return FALSE;
+    }
+
+  device_event_controller = 
+    Accessibility_Registry_getDeviceEventController (cspi_registry (), cspi_ev ());
+
+  cspi_return_val_if_ev ("getting keystroke listener", FALSE);
+
+  event_types._buffer = Accessibility_EventTypeSeq_allocbuf (2);
+  event_types._length = 2;
+  event_types._buffer[0] = Accessibility_BUTTON_PRESSED_EVENT;
+  event_types._buffer[1] = Accessibility_BUTTON_RELEASED_EVENT;
+
+  Accessibility_DeviceEventController_deregisterDeviceEventListener (
+    device_event_controller,
+    cspi_event_listener_get_corba (listener),
+    &event_types,    
+    cspi_ev ());
+
+  cspi_release_unref (device_event_controller);
+
+  return TRUE;
+}
+
+/**
  * SPI_generateKeyboardEvent:
  * @keyval: a long integer indicating the keycode or keysym of the key event
  *           being synthesized.
Index: cspi/bonobo/cspi-bonobo-listener.c
===================================================================
RCS file: /cvs/gnome/at-spi/cspi/bonobo/cspi-bonobo-listener.c,v
retrieving revision 1.15
diff -u -r1.15 cspi-bonobo-listener.c
--- cspi/bonobo/cspi-bonobo-listener.c	16 Aug 2002 14:44:22 -0000	1.15
+++ cspi/bonobo/cspi-bonobo-listener.c	14 Nov 2002 22:06:47 -0000
@@ -3,6 +3,7 @@
  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
  *
  * Copyright 2002 Ximian Inc.
+ * Copyright 2002 Sun Microsystems, Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -29,14 +30,14 @@
   union
     {
       AccessibleEventListenerCB     event;
-      AccessibleKeystrokeListenerCB key_event;
+      AccessibleDeviceListenerCB    device_event;
       gpointer                      method;
     } cb;
   gpointer user_data;
 } EventHandler;
 
 GObjectClass *event_parent_class;
-GObjectClass *keystroke_parent_class;
+GObjectClass *device_parent_class;
 
 /*
  * Misc. helpers.
@@ -175,55 +176,48 @@
   listener->callbacks = cspi_event_list_remove_by_cb (listener->callbacks, callback);
 }
 
-/*
- * Key event dispatcher
+/* 
+ * Device event handler
  */
 static gboolean
-cspi_key_event (SpiKeystrokeListener            *listener,
-		const Accessibility_DeviceEvent *keystroke)
+cspi_device_event (SpiDeviceListener               *listener,
+		   const Accessibility_DeviceEvent *event)
 {
   GList *l;
-  CSpiKeystrokeListener *clistener = (CSpiKeystrokeListener *) listener;
-  AccessibleKeystroke akeystroke;
+  CSpiDeviceListener *clistener = (CSpiDeviceListener *) listener;
+  AccessibleDeviceEvent anevent;
   gboolean handled = FALSE;
 
-#ifdef SPI_KEYEVENT_DEBUG
-  fprintf (stderr, "%s%c",
-	   (keystroke->modifiers & SPI_KEYMASK_ALT)?"Alt-":"",
-	   ((keystroke->modifiers & SPI_KEYMASK_SHIFT)^(keystroke->modifiers & SPI_KEYMASK_SHIFTLOCK))?
-	   (char) toupper((int) keystroke->keyID) : (char) tolower((int) keystroke->keyID));
-  
-  fprintf (stderr, "Key:\tsym %ld\n\tmods %x\n\tcode %d\n\ttime %ld\n",
-	   (long) keystroke->keyID,
-	   (unsigned int) keystroke->modifiers,
-	   (int) keystroke->keycode,
-	   (long int) keystroke->timestamp);
-#endif
-
-  switch (keystroke->type)
+  switch (event->type)
     {
-      case Accessibility_KEY_PRESSED:
-	akeystroke.type = SPI_KEY_PRESSED;
+      case Accessibility_KEY_PRESSED_EVENT:
+	anevent.type = SPI_KEY_PRESSED;
+	break;
+      case Accessibility_KEY_RELEASED_EVENT:
+	anevent.type = SPI_KEY_RELEASED;
 	break;
-      case Accessibility_KEY_RELEASED:
-	akeystroke.type = SPI_KEY_RELEASED;
+      case Accessibility_BUTTON_PRESSED_EVENT:
+	anevent.type = SPI_BUTTON_PRESSED;
+	break;
+      case Accessibility_BUTTON_RELEASED_EVENT:
+	anevent.type = SPI_BUTTON_RELEASED;
 	break;
       default:
-	akeystroke.type = 0;
+	anevent.type = 0;
 	break;
     }
-  akeystroke.keyID     = keystroke->id;
-  akeystroke.keycode   = keystroke->hw_code;
-  akeystroke.timestamp = keystroke->timestamp;
-  akeystroke.keystring = g_strdup (keystroke->event_string);
-  akeystroke.modifiers = keystroke->modifiers;
+  anevent.keyID     = event->id;
+  anevent.keycode   = event->hw_code;
+  anevent.timestamp = event->timestamp;
+  anevent.keystring = g_strdup (event->event_string);
+  anevent.modifiers = event->modifiers;
 
   /* FIXME: re-enterancy hazard on this list */
   for (l = clistener->callbacks; l; l = l->next)
     {
       EventHandler *eh = l->data;
 
-      if ((handled = eh->cb.key_event (&akeystroke, eh->user_data)))
+      if ((handled = eh->cb.device_event (&anevent, eh->user_data)))
         {
 	  break;
 	}
@@ -233,15 +227,14 @@
 }
 
 static void
-cspi_keystroke_listener_init (CSpiKeystrokeListener *listener)
+cspi_device_listener_init (CSpiDeviceListener *listener)
 {
 }
 
-
 static void
-cspi_keystroke_listener_finalize (GObject *object)
+cspi_device_listener_finalize (GObject *object)
 {
-  CSpiKeystrokeListener *listener = (CSpiKeystrokeListener *) object;
+  CSpiDeviceListener *listener = (CSpiDeviceListener *) object;
   GList *l;
   
   for (l = listener->callbacks; l; l = l->next)
@@ -251,54 +244,52 @@
   
   g_list_free (listener->callbacks);
 
-  keystroke_parent_class->finalize (object);
+  device_parent_class->finalize (object);
 }
 
 static void
-cspi_keystroke_listener_class_init (CSpiKeystrokeListenerClass *klass)
+cspi_device_listener_class_init (CSpiDeviceListenerClass *klass)
 {
   GObjectClass *object_class = (GObjectClass *) klass;
 
-  keystroke_parent_class = g_type_class_peek_parent (klass);
-  object_class->finalize = cspi_keystroke_listener_finalize;
+  device_parent_class = g_type_class_peek_parent (klass);
+  object_class->finalize = cspi_device_listener_finalize;
 
-  klass->key_event = cspi_key_event;
+  klass->device_event = cspi_device_event;
 }
 
-BONOBO_TYPE_FUNC (CSpiKeystrokeListener, 
-		  spi_keystroke_listener_get_type (),
-		  cspi_keystroke_listener);
+BONOBO_TYPE_FUNC (CSpiDeviceListener, 
+		  spi_device_listener_get_type (),
+		  cspi_device_listener);
 
 gpointer
-cspi_keystroke_listener_new (void)
+cspi_device_listener_new (void)
 {
-  CSpiEventListener *listener;
-
-  listener = g_object_new (cspi_keystroke_listener_get_type (), NULL);
+  CSpiEventListener *listener = g_object_new (cspi_device_listener_get_type (), NULL);
 
   return listener;
 }
 
 void
-cspi_keystroke_listener_add_cb (AccessibleKeystrokeListener  *al,
-				AccessibleKeystrokeListenerCB callback,
-				void                         *user_data)
+cspi_device_listener_add_cb (AccessibleDeviceListener  *al,
+			     AccessibleDeviceListenerCB callback,
+			     void                      *user_data)
 {
-  CSpiKeystrokeListener *listener = al;
+  CSpiDeviceListener *listener = al;
 
-  g_return_if_fail (CSPI_IS_KEYSTROKE_LISTENER (listener));
+  g_return_if_fail (CSPI_IS_DEVICE_LISTENER (listener));
 
   listener->callbacks = g_list_prepend (listener->callbacks,
 					cspi_event_handler_new (callback, user_data));
 }
 
 void
-cspi_keystroke_listener_remove_cb (AccessibleKeystrokeListener  *al,
-				   AccessibleKeystrokeListenerCB callback)
+cspi_device_listener_remove_cb (AccessibleDeviceListener  *al,
+				AccessibleDeviceListenerCB callback)
 {
-  CSpiKeystrokeListener *listener = al;
+  CSpiDeviceListener *listener = al;
 
-  g_return_if_fail (CSPI_IS_KEYSTROKE_LISTENER (listener));
+  g_return_if_fail (CSPI_IS_DEVICE_LISTENER (listener));
 
   listener->callbacks = cspi_event_list_remove_by_cb (listener->callbacks, callback);
 }
@@ -310,7 +301,7 @@
 }
 
 void
-cspi_keystroke_listener_unref (AccessibleKeystrokeListener *listener)
+cspi_device_listener_unref (AccessibleDeviceListener *listener)
 {
   bonobo_object_unref (BONOBO_OBJECT (listener));
 }
@@ -323,7 +314,7 @@
 }
 
 CORBA_Object
-cspi_keystroke_listener_get_corba (AccessibleKeystrokeListener *listener)
+cspi_device_listener_get_corba (AccessibleDeviceListener *listener)
 {
   return BONOBO_OBJREF (listener);
 }
Index: cspi/bonobo/cspi-bonobo-listener.h
===================================================================
RCS file: /cvs/gnome/at-spi/cspi/bonobo/cspi-bonobo-listener.h,v
retrieving revision 1.7
diff -u -r1.7 cspi-bonobo-listener.h
--- cspi/bonobo/cspi-bonobo-listener.h	16 Aug 2002 14:44:22 -0000	1.7
+++ cspi/bonobo/cspi-bonobo-listener.h	14 Nov 2002 22:06:47 -0000
@@ -24,7 +24,7 @@
 #define __SPI_LISTENER_IMP_H__
 
 #include <libspi/eventlistener.h>
-#include <libspi/keystrokelistener.h>
+#include <libspi/devicelistener.h>
 #include <cspi/spi-impl.h>
 #include <cspi/spi-listener.h>
 
@@ -44,19 +44,20 @@
 
 GType cspi_event_listener_get_type (void);
 
-#define CSPI_KEYSTROKE_LISTENER_TYPE        (cspi_keystroke_listener_get_type ())
-#define CSPI_KEYSTROKE_LISTENER(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), CSPI_KEYSTROKE_LISTENER_TYPE, CSpiKeystrokeListener))
-#define CSPI_KEYSTROKE_LISTENER_CLASS(k)    (G_TYPE_CHECK_CLASS_CAST((k), CSPI_KEYSTROKE_LISTENER_TYPE, CSpiKeystrokeListenerClass))
-#define CSPI_IS_KEYSTROKE_LISTENER(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), CSPI_KEYSTROKE_LISTENER_TYPE))
-#define CSPI_IS_KEYSTROKE_LISTENER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CSPI_KEYSTROKE_LISTENER_TYPE))
+#define CSPI_DEVICE_LISTENER_TYPE        (cspi_device_listener_get_type ())
+#define CSPI_DEVICE_LISTENER(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), CSPI_DEVICE_LISTENER_TYPE, CSpiDeviceListener))
+#define CSPI_DEVICE_LISTENER_CLASS(k)    (G_TYPE_CHECK_CLASS_CAST((k), CSPI_DEVICE_LISTENER_TYPE, CSpiDeviceListenerClass))
+#define CSPI_IS_DEVICE_LISTENER(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), CSPI_DEVICE_LISTENER_TYPE))
+#define CSPI_IS_DEVICE_LISTENER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CSPI_DEVICE_LISTENER_TYPE))
 
 typedef struct {
-	SpiKeystrokeListener parent;
-	GList               *callbacks;
-} CSpiKeystrokeListener;
-typedef SpiKeystrokeListenerClass CSpiKeystrokeListenerClass;
+	SpiDeviceListener parent;
+	GList            *callbacks;
+} CSpiDeviceListener;
+typedef SpiDeviceListenerClass CSpiDeviceListenerClass;
 
-GType cspi_keystroke_listener_get_type (void);
+GType cspi_device_listener_get_type (void);
+gpointer cspi_device_listener_new (void);
 
 G_END_DECLS
 
Index: docs/reference/cspi/tmpl/spi_registry.sgml
===================================================================
RCS file: /cvs/gnome/at-spi/docs/reference/cspi/tmpl/spi_registry.sgml,v
retrieving revision 1.11
diff -u -r1.11 spi_registry.sgml
--- docs/reference/cspi/tmpl/spi_registry.sgml	17 Apr 2002 00:20:54 -0000	1.11
+++ docs/reference/cspi/tmpl/spi_registry.sgml	14 Nov 2002 22:06:47 -0000
@@ -83,13 +83,11 @@
 </para>
 
 
-<!-- ##### ENUM AccessibleKeyEventType ##### -->
+<!-- ##### TYPEDEF AccessibleKeyEventType ##### -->
 <para>
 
 </para>
 
- SPI_KEY_PRESSED: 
- SPI_KEY_RELEASED: 
 
 <!-- ##### ENUM AccessibleKeyListenerSyncType ##### -->
 <para>
Index: idl/Accessibility_Event.idl
===================================================================
RCS file: /cvs/gnome/at-spi/idl/Accessibility_Event.idl,v
retrieving revision 1.9
diff -u -r1.9 Accessibility_Event.idl
--- idl/Accessibility_Event.idl	19 Jun 2002 13:47:09 -0000	1.9
+++ idl/Accessibility_Event.idl	14 Nov 2002 22:06:47 -0000
@@ -38,6 +38,9 @@
 
   interface EventListener : Bonobo::Unknown {
     void notifyEvent (in Event e);
+    void notifyEventFull (in Event e, in any data);
+    void unImplemented_ ();
+    void unImplemented2_ ();
   };
 };
 
Index: idl/Accessibility_Registry.idl
===================================================================
RCS file: /cvs/gnome/at-spi/idl/Accessibility_Registry.idl,v
retrieving revision 1.19
diff -u -r1.19 Accessibility_Registry.idl
--- idl/Accessibility_Registry.idl	3 Jun 2002 14:44:49 -0000	1.19
+++ idl/Accessibility_Registry.idl	14 Nov 2002 22:06:47 -0000
@@ -153,6 +153,7 @@
 	void unImplemented2 ();
     };
 
+  /* Deprecated, DO NOT USE! */
   enum KeyEventType {
     KEY_PRESSED,
     KEY_RELEASED
@@ -160,7 +161,9 @@
 
   enum EventType {
     KEY_PRESSED_EVENT,
-    KEY_RELEASED_EVENT
+    KEY_RELEASED_EVENT,
+    BUTTON_PRESSED_EVENT,
+    BUTTON_RELEASED_EVENT
   };
 
   enum KeySynthType {
@@ -208,7 +211,8 @@
   };	
 
   typedef sequence< KeyDefinition > KeySet;
-  typedef sequence< KeyEventType > KeyEventTypeSeq;
+  typedef sequence< EventType > KeyEventTypeSeq;
+  typedef sequence< EventType > EventTypeSeq;
 
   interface DeviceEventListener : Bonobo::Unknown {
         boolean notifyEvent (in DeviceEvent event);
@@ -254,6 +258,34 @@
 					  in KeySet keys,
 					  in ControllerEventMask mask,
 					  in KeyEventTypeSeq type);
+    
+  	/**
+         * registerDeviceEventListener:
+         * @listener: a @DeviceEventListener which will intercept events.
+	 * @typeseq:  an @EventTypeSeq indicating which event types to listen for.
+	 * Returns: %true if successful, %false if not
+         *
+         * Register to intercept events, and either pass them on or
+         * consume them. To listen to keyboard events use registerKeystrokeListener
+	 * instead.
+         *
+	 **/
+        boolean registerDeviceEventListener (in DeviceEventListener listener,
+					     in EventTypeSeq typeseq);
+    
+  	/**
+         * deregisterDeviceEventListener:
+         * @listener: a @DeviceEventListener which will intercept events.
+	 * @typeseq:  an @EventTypeSeq indicating which event types to stop
+	 *            listening for.
+	 *
+	 * Returns: void
+         *
+         * De-register a previously registered keyboard eventlistener.
+         *
+	 **/
+        void deregisterDeviceEventListener (in DeviceEventListener listener,
+					    in EventTypeSeq typeseq);
     
         boolean notifyListenersSync (in DeviceEvent event);
 
Index: libspi/Makefile.am
===================================================================
RCS file: /cvs/gnome/at-spi/libspi/Makefile.am,v
retrieving revision 1.32
diff -u -r1.32 Makefile.am
--- libspi/Makefile.am	28 Aug 2002 14:40:21 -0000	1.32
+++ libspi/Makefile.am	14 Nov 2002 22:06:47 -0000
@@ -24,6 +24,7 @@
 	hyperlink.h		\
 	hypertext.h		\
 	image.h			\
+	devicelistener.h	\
 	keystrokelistener.h	\
 	keymasks.h		\
 	libspi.h		\
@@ -74,7 +75,7 @@
 	hyperlink.c		\
 	hypertext.c		\
 	image.c			\
-	keystrokelistener.c	\
+	devicelistener.c	\
 	relation.c		\
 	remoteobject.c		\
 	selection.c		\
Index: libspi/keystrokelistener.h
===================================================================
RCS file: /cvs/gnome/at-spi/libspi/keystrokelistener.h,v
retrieving revision 1.10
diff -u -r1.10 keystrokelistener.h
--- libspi/keystrokelistener.h	13 Sep 2002 13:09:01 -0000	1.10
+++ libspi/keystrokelistener.h	14 Nov 2002 22:06:47 -0000
@@ -24,35 +24,22 @@
 #ifndef SPI_KEYSTROKE_LISTENER_H_
 #define SPI_KEYSTROKE_LISTENER_H_
 
-#include <bonobo/bonobo-object.h>
-#include <atk/atkobject.h>
-#include <libspi/Accessibility.h>
-#include <libspi/keymasks.h>
-
 G_BEGIN_DECLS
 
-#define SPI_KEYSTROKE_LISTENER_TYPE        (spi_keystroke_listener_get_type ())
-#define SPI_KEYSTROKE_LISTENER(o)          (G_TYPE_CHECK_INSTANCE_CAST ((o), SPI_KEYSTROKE_LISTENER_TYPE, SpiKeystrokeListener))
-#define SPI_KEYSTROKE_LISTENER_CLASS(k)    (G_TYPE_CHECK_CLASS_CAST((k), SPI_KEYSTROKE_LISTENER_TYPE, SpiKeystrokeListenerClass))
+#include <libspi/devicelistener.h>
+
+#define SPI_KEYSTROKE_LISTENER_TYPE        SPI_DEVICE_LISTENER_TYPE
+#define SPI_KEYSTROKE_LISTENER(o)          SPI_DEVICE_LISTENER(o)
+#define SPI_KEYSTROKE_LISTENER_CLASS(k)    SPI_DEVICE_LISTENER_CLASS(k)
 #define SPI_IS_KEYSTROKE_LISTENER(o)       (G_TYPE_CHECK_INSTANCE_TYPE ((o), SPI_KEYSTROKE_LISTENER_TYPE))
 #define SPI_IS_KEYSTROKE_LISTENER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SPI_KEYSTROKE_LISTENER_TYPE))
 
-typedef struct _SpiKeystrokeListener SpiKeystrokeListener;
-
-struct _SpiKeystrokeListener {
-        BonoboObject parent;
-};
-
-typedef struct {
-        BonoboObjectClass parent_class;
-        POA_Accessibility_DeviceEventListener__epv epv;
+typedef struct _SpiDeviceListener SpiKeystrokeListener;
 
-	gboolean (*key_event) (SpiKeystrokeListener *listener,
-			       const Accessibility_DeviceEvent *key);
-} SpiKeystrokeListenerClass;
+typedef SpiDeviceListenerClass SpiKeystrokeListenerClass;
 
-GType                  spi_keystroke_listener_get_type        (void);
-SpiKeystrokeListener  *spi_keystroke_listener_new             (void);
+#define spi_keystroke_listener_get_type spi_device_listener_get_type
+#define spi_keystroke_listener_new      spi_device_listener_new
 
 G_END_DECLS
 
Index: libspi/libspi.h
===================================================================
RCS file: /cvs/gnome/at-spi/libspi/libspi.h,v
retrieving revision 1.6
diff -u -r1.6 libspi.h
--- libspi/libspi.h	19 Apr 2002 09:09:51 -0000	1.6
+++ libspi/libspi.h	14 Nov 2002 22:06:47 -0000
@@ -41,7 +41,7 @@
 #include <libspi/value.h>
 #include <libspi/listener.h>
 #include <libspi/eventlistener.h>
-#include <libspi/keystrokelistener.h>
+#include <libspi/devicelistener.h>
 #include <libspi/keymasks.h>
 #include <libspi/remoteobject.h>
 
Index: registryd/deviceeventcontroller.c
===================================================================
RCS file: /cvs/gnome/at-spi/registryd/deviceeventcontroller.c,v
retrieving revision 1.50
diff -u -r1.50 deviceeventcontroller.c
--- registryd/deviceeventcontroller.c	23 Oct 2002 15:57:44 -0000	1.50
+++ registryd/deviceeventcontroller.c	14 Nov 2002 22:06:49 -0000
@@ -82,6 +82,7 @@
 typedef struct {
   CORBA_Object          object;
   SpiDeviceTypeCategory type;
+  Accessibility_EventTypeSeq    *typeseq;
 } DEControllerListener;
 
 typedef struct {
@@ -89,7 +90,6 @@
 
   Accessibility_KeySet             *keys;
   Accessibility_ControllerEventMask mask;
-  Accessibility_KeyEventTypeSeq    *typeseq;
   Accessibility_EventListenerMode  *mode;	
 } DEControllerKeyListener;
 
@@ -98,6 +98,13 @@
 	unsigned int last_release_keycode;
 	struct timeval last_press_time;
 	struct timeval last_release_time;
+	int have_xkb;
+	int xkb_major_extension_opcode;
+	int xkb_base_event_code;
+	int xkb_base_error_code;
+	unsigned int xkb_latch_mask;
+	unsigned int pending_xkb_mod_relatch_mask;
+	XkbDescPtr xkb_desc;
 } DEControllerPrivateData;
 
 static void     spi_controller_register_with_devices          (SpiDEController           *controller);
@@ -108,10 +115,18 @@
 							       CORBA_Environment         *ev);
 static void     spi_device_event_controller_forward_key_event (SpiDEController           *controller,
 							       const XEvent              *event);
+static void     spi_deregister_controller_device_listener (SpiDEController            *controller,
+					                   DEControllerListener *listener,
+					                   CORBA_Environment          *ev);
 static void     spi_deregister_controller_key_listener (SpiDEController         *controller,
 							DEControllerKeyListener *key_listener,
 							CORBA_Environment       *ev);
+static gboolean spi_controller_notify_mouselisteners (SpiDEController                 *controller,
+						      const Accessibility_DeviceEvent *event,
+						      CORBA_Environment               *ev);
 
+static gboolean spi_eventtype_seq_contains_event (Accessibility_EventTypeSeq      *type_seq,
+						  const Accessibility_DeviceEvent *event);
 static gboolean spi_clear_error_state (void);
 static gboolean spi_dec_poll_mouse_moved (gpointer data);
 static gboolean spi_dec_poll_mouse_moving (gpointer data);
@@ -169,14 +184,17 @@
 spi_dec_poll_mouse_moved (gpointer data)
 {
   SpiRegistry *registry = SPI_REGISTRY (data);
+  SpiDEController *controller = registry->de_controller;
   CORBA_Environment ev;
   Accessibility_Event e;
+  Accessibility_DeviceEvent mouse_e;
   Window root_return, child_return;
   int win_x_return,win_y_return;
   int x, y;
   int poll_count_modulus = 10;
   unsigned int mask_return;
   gchar event_name[24];
+  gboolean is_consumed;
   Display *display = spi_get_display ();
 
   if (display != NULL)
@@ -211,14 +229,30 @@
 				   button_number);
 #endif
 			  snprintf (event_name, 22, "mouse:button:%dr", button_number);
+			  /* TODO: distinguish between physical and 
+			   * logical buttons 
+			   */
+			  mouse_e.type      = Accessibility_BUTTON_RELEASED_EVENT;
+			  mouse_e.id        = button_number;
+			  mouse_e.hw_code   = button_number;
+                          mouse_e.modifiers = (CORBA_unsigned_short) 
+			                       mouse_mask_state; 
+			  mouse_e.timestamp = 0;
+			  mouse_e.event_string = CORBA_string_dup ("");
+			  mouse_e.is_text   = CORBA_FALSE;
+			  is_consumed = 
+			    spi_controller_notify_mouselisteners (controller, 
+								  &mouse_e, 
+								  &ev);
 			  e.type = event_name;
 			  e.source = BONOBO_OBJREF (registry->desktop);
 			  e.detail1 = last_mouse_pos->x;
 			  e.detail2 = last_mouse_pos->y;
 			  CORBA_exception_init (&ev);
-			  Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry),
-							      &e,
-							      &ev);
+			  if (!is_consumed)
+			    Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry),
+								&e,
+								&ev);  
 		  }
 	  }
 	  if ((mask_return & key_modifier_mask) !=
@@ -315,7 +349,7 @@
 
   if (display)
     {
-      XGrabButton (display, AnyButton, 0,
+      XGrabButton (display, AnyButton, AnyModifier,
 		   gdk_x11_get_default_root_xwindow (),
 		   True, ButtonPressMask | ButtonReleaseMask,
 		   GrabModeSync, GrabModeAsync, None, None);
@@ -330,7 +364,7 @@
 spi_dec_key_listener_new (CORBA_Object                            l,
 			  const Accessibility_KeySet             *keys,
 			  const Accessibility_ControllerEventMask mask,
-			  const Accessibility_KeyEventTypeSeq    *typeseq,
+			  const Accessibility_EventTypeSeq    *typeseq,
 			  const Accessibility_EventListenerMode  *mode,
 			  CORBA_Environment                      *ev)
 {
@@ -339,7 +373,7 @@
   key_listener->listener.type = SPI_DEVICE_TYPE_KBD;
   key_listener->keys = ORBit_copy_value (keys, TC_Accessibility_KeySet);
   key_listener->mask = mask;
-  key_listener->typeseq = ORBit_copy_value (typeseq, TC_Accessibility_KeyEventTypeSeq);
+  key_listener->listener.typeseq = ORBit_copy_value (typeseq, TC_Accessibility_EventTypeSeq);
   if (mode)
     key_listener->mode = ORBit_copy_value (mode, TC_Accessibility_EventListenerMode);
   else
@@ -356,6 +390,30 @@
   return key_listener;	
 }
 
+static DEControllerListener *
+spi_dec_listener_new (CORBA_Object                            l,
+		      const Accessibility_EventTypeSeq    *typeseq,
+		      CORBA_Environment                      *ev)
+{
+  DEControllerListener *listener = g_new0 (DEControllerListener, 1);
+  listener->object = bonobo_object_dup_ref (l, ev);
+  listener->type = SPI_DEVICE_TYPE_MOUSE;
+  listener->typeseq = ORBit_copy_value (typeseq, TC_Accessibility_EventTypeSeq);
+
+  return listener;	
+}
+
+static DEControllerListener *
+spi_listener_clone (DEControllerListener *listener, CORBA_Environment *ev)
+{
+  DEControllerListener *clone = g_new0 (DEControllerListener, 1);
+  clone->object =
+	  CORBA_Object_duplicate (listener->object, ev);
+  clone->type = listener->type;
+  clone->typeseq = ORBit_copy_value (listener->typeseq, TC_Accessibility_EventTypeSeq);
+  return clone;
+}
+
 static DEControllerKeyListener *
 spi_key_listener_clone (DEControllerKeyListener *key_listener, CORBA_Environment *ev)
 {
@@ -365,7 +423,7 @@
   clone->listener.type = SPI_DEVICE_TYPE_KBD;
   clone->keys = ORBit_copy_value (key_listener->keys, TC_Accessibility_KeySet);
   clone->mask = key_listener->mask;
-  clone->typeseq = ORBit_copy_value (key_listener->typeseq, TC_Accessibility_KeyEventTypeSeq);
+  clone->listener.typeseq = ORBit_copy_value (key_listener->listener.typeseq, TC_Accessibility_EventTypeSeq);
   if (key_listener->mode)
     clone->mode = ORBit_copy_value (key_listener->mode, TC_Accessibility_EventListenerMode);
   else
@@ -376,7 +434,7 @@
 static void
 spi_key_listener_data_free (DEControllerKeyListener *key_listener, CORBA_Environment *ev)
 {
-  CORBA_free (key_listener->typeseq);
+  CORBA_free (key_listener->listener.typeseq);
   CORBA_free (key_listener->keys);
   g_free (key_listener);
 }
@@ -389,6 +447,14 @@
 }
 
 static void
+spi_listener_clone_free (DEControllerListener *clone, CORBA_Environment *ev)
+{
+  CORBA_Object_release (clone->object, ev);
+  CORBA_free (clone->typeseq);
+  g_free (clone);
+}
+
+static void
 spi_dec_key_listener_free (DEControllerKeyListener *key_listener,
 			   CORBA_Environment       *ev)
 {
@@ -527,22 +593,109 @@
       else
 	      return TRUE;
       break;
-    default:
+  case SPI_DEVICE_TYPE_MOUSE:
+      controller->mouse_listeners = g_list_prepend (controller->mouse_listeners, listener);
+      break;
+  default:
+      fprintf (stderr, "WARNING: listener registration for unknown device type.\n");
       break;
   }
   return FALSE; 
 }
 
+static gboolean
+spi_controller_notify_mouselisteners (SpiDEController                 *controller,
+				      const Accessibility_DeviceEvent *event,
+				      CORBA_Environment               *ev)
+{
+  GList   *l;
+  GSList  *notify = NULL, *l2;
+  GList  **listeners = &controller->mouse_listeners;
+  gboolean is_consumed;
+
+  if (!listeners)
+    {
+      return FALSE;
+    }
+
+  for (l = *listeners; l; l = l->next)
+    {
+       DEControllerListener *listener = l->data;
+
+       if (spi_eventtype_seq_contains_event (listener->typeseq, event))
+         {
+           Accessibility_DeviceEventListener ls = listener->object;
+
+	   if (ls != CORBA_OBJECT_NIL)
+	     {
+	       /* we clone (don't dup) the listener, to avoid refcount inc. */
+	       notify = g_slist_prepend (notify,
+					 spi_listener_clone (listener, ev));
+	     }
+         }
+    }
+
+#ifdef SPI_KEYEVENT_DEBUG
+  if (!notify)
+    {
+      g_print ("no match for event\n");
+    }
+#endif
+
+  is_consumed = FALSE;
+  for (l2 = notify; l2 && !is_consumed; l2 = l2->next)
+    {
+      DEControllerListener *listener = l2->data;	    
+      Accessibility_DeviceEventListener ls = listener->object;
+
+      fprintf (stderr, "notifying mouse listener\n");
+      CORBA_exception_init (ev);
+      is_consumed = Accessibility_DeviceEventListener_notifyEvent (ls, event, ev);
+      fprintf (stderr, "%sconsumed\n", is_consumed ? "" : "not ");
+
+      if (BONOBO_EX (ev))
+        {
+          is_consumed = FALSE;
+	  fprintf (stderr, "error notifying listener, removing it\n");
+	  spi_deregister_controller_device_listener (controller, listener,
+						     ev);
+          CORBA_exception_free (ev);
+        }
+
+      CORBA_Object_release (ls, ev);
+    }
+
+  for (; l2; l2 = l2->next)
+    {
+      DEControllerListener *listener = l2->data;	    
+      spi_listener_clone_free (listener, ev);
+      /* clone doesn't have its own ref, so don't use spi_device_listener_free */
+    }
+
+  g_slist_free (notify);
+
+#ifdef SPI_DEBUG
+  if (is_consumed) g_message ("consumed\n");
+#endif
+  return is_consumed;
+}
+
 static void
 spi_device_event_controller_forward_mouse_event (SpiDEController *controller,
 						 XEvent *xevent)
 {
   Accessibility_Event e;
+  Accessibility_DeviceEvent mouse_e;
   CORBA_Environment ev;
   gchar event_name[24];
-  int button = ((XButtonEvent *) xevent)->button;
+  gboolean is_consumed = FALSE;
+  gboolean xkb_mod_unlatch_occurred;
+  DEControllerPrivateData *priv;
+  XButtonEvent *xbutton_event = (XButtonEvent *) xevent;
+
+  int button = xbutton_event->button;
   
-  unsigned int mouse_button_state = ((XButtonEvent *) xevent)->state;
+  unsigned int mouse_button_state = xbutton_event->state;
 
   switch (button)
     {
@@ -567,23 +720,51 @@
 
 #ifdef SPI_DEBUG  
   fprintf (stderr, "mouse button %d %s (%x)\n",
-	   ((XButtonEvent *) xevent)->button, 
+	   xbutton_event->button, 
 	   (xevent->type == ButtonPress) ? "Press" : "Release",
 	   mouse_button_state);
 #endif
   snprintf (event_name, 22, "mouse:button:%d%c", button,
 	    (xevent->type == ButtonPress) ? 'p' : 'r');
 
+  /* TODO: distinguish between physical and logical buttons */
+  mouse_e.type      = (xevent->type == ButtonPress) ? 
+                      Accessibility_BUTTON_PRESSED_EVENT :
+                      Accessibility_BUTTON_RELEASED_EVENT;
+  mouse_e.id        = button;
+  mouse_e.hw_code   = button;
+  mouse_e.modifiers = (CORBA_unsigned_short) xbutton_event->state;
+  mouse_e.timestamp = (CORBA_unsigned_long) xbutton_event->time;
+  mouse_e.event_string = CORBA_string_dup ("");
+  mouse_e.is_text   = CORBA_FALSE;
+  is_consumed = spi_controller_notify_mouselisteners (controller, &mouse_e, &ev);
+
+  fprintf (stderr, "mouse listeners notified\n");
   e.type = CORBA_string_dup (event_name);
   e.source = BONOBO_OBJREF (controller->registry->desktop);
   e.detail1 = last_mouse_pos->x;
   e.detail2 = last_mouse_pos->y;
   CORBA_exception_init (&ev);
+  
   Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry),
 				      &e,
 				      &ev);
+
+  xkb_mod_unlatch_occurred = (xevent->type == ButtonPress ||
+			      xevent->type == ButtonRelease);
   
-  XAllowEvents (spi_get_display (), ReplayPointer, CurrentTime);
+  /* if client wants to consume this event, and XKB latch state was
+   *   unset by this button event, we reset it
+   */
+  if (is_consumed && xkb_mod_unlatch_occurred)
+    {
+      priv = g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);	    
+      priv->pending_xkb_mod_relatch_mask |= priv->xkb_latch_mask; 
+    }
+  
+  XAllowEvents (spi_get_display (),
+		(is_consumed) ? SyncPointer : ReplayPointer,
+		CurrentTime);
 }
 
 static GdkFilterReturn
@@ -591,19 +772,68 @@
 {
   XEvent *xevent = gdk_xevent;
   SpiDEController *controller;
+  DEControllerPrivateData *priv;
+  Display *display = spi_get_display ();
+  controller = SPI_DEVICE_EVENT_CONTROLLER (data);
+  priv = (DEControllerPrivateData *)
+	  g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);  
 
   if (xevent->type == KeyPress || xevent->type == KeyRelease)
     {
-      controller = SPI_DEVICE_EVENT_CONTROLLER (data);
       spi_device_event_controller_forward_key_event (controller, xevent);
-      /* FIXME: is this right ? */
       return GDK_FILTER_CONTINUE;
     }
   if (xevent->type == ButtonPress || xevent->type == ButtonRelease)
     {
-      controller = SPI_DEVICE_EVENT_CONTROLLER (data);
       spi_device_event_controller_forward_mouse_event (controller, xevent);
     }
+  if (xevent->type == priv->xkb_base_event_code)
+    {
+      XkbAnyEvent * xkb_ev = (XkbAnyEvent *) xevent;
+
+      if (xkb_ev->xkb_type == XkbStateNotify)
+        {
+	  XkbStateNotifyEvent *xkb_snev =
+		  (XkbStateNotifyEvent *) xkb_ev;
+	  priv->xkb_latch_mask = xkb_snev->latched_mods;
+	  fprintf (stderr, "latch mask = %x\n", priv->xkb_latch_mask);
+	  if (priv->pending_xkb_mod_relatch_mask)
+	    {
+	      unsigned int feedback_mask;
+	      fprintf (stderr, "relatching %x\n",
+		       priv->pending_xkb_mod_relatch_mask);
+	      /* temporarily turn off the latch bell, if it's on */
+	      XkbGetControls (display,
+			      XkbAccessXFeedbackMask,
+			      priv->xkb_desc);
+	      feedback_mask = priv->xkb_desc->ctrls->ax_options;
+	      if (feedback_mask & XkbAX_StickyKeysFBMask)
+	      {
+	        XkbControlsChangesRec changes = {XkbAccessXFeedbackMask,
+						 0, False};      
+	        priv->xkb_desc->ctrls->ax_options
+			      &= ~(XkbAX_StickyKeysFBMask);
+	        XkbChangeControls (display, priv->xkb_desc, &changes);
+	      }
+	      XkbLatchModifiers (display,
+				 XkbUseCoreKbd,
+				 priv->pending_xkb_mod_relatch_mask,
+				 priv->pending_xkb_mod_relatch_mask);
+	      if (feedback_mask & XkbAX_StickyKeysFBMask)
+	      {	
+	        XkbControlsChangesRec changes = {XkbAccessXFeedbackMask,
+						 0, False};      
+		priv->xkb_desc->ctrls->ax_options = feedback_mask;
+		XkbChangeControls (display, priv->xkb_desc, &changes);
+	      }
+	      fprintf (stderr, "relatched %x\n",
+		       priv->pending_xkb_mod_relatch_mask);
+	      priv->pending_xkb_mod_relatch_mask = 0;
+	    }
+	}
+        else
+		fprintf (stderr, "XKB event %d\n", xkb_ev->xkb_type);
+    }
   
   return GDK_FILTER_CONTINUE;
 }
@@ -626,10 +856,25 @@
 static void
 spi_controller_register_with_devices (SpiDEController *controller)
 {
+  DEControllerPrivateData *priv = (DEControllerPrivateData *) 
+	  g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);	 
+
+  priv->xkb_desc = XkbGetMap (spi_get_display (), 0, XkbUseCoreKbd);
+
   /* calls to device-specific implementations and routines go here */
   /* register with: keyboard hardware code handler */
   /* register with: (translated) keystroke handler */
 
+  priv->have_xkb = XkbQueryExtension (spi_get_display (),
+				      &priv->xkb_major_extension_opcode,
+				      &priv->xkb_base_event_code,
+				      &priv->xkb_base_error_code, NULL, NULL);
+  if (priv->have_xkb)
+    {
+      XkbSelectEvents (spi_get_display (),
+		       XkbUseCoreKbd,
+		       XkbStateNotifyMask, XkbStateNotifyMask);	    
+    }	
   gdk_window_add_filter (NULL, global_filter_fn, controller);
 
   gdk_window_set_events (gdk_get_default_root_window (),
@@ -686,8 +931,8 @@
 }
 
 static gboolean
-spi_key_eventtype_seq_contains_event (Accessibility_KeyEventTypeSeq   *type_seq,
-				      const Accessibility_DeviceEvent *key_event)
+spi_eventtype_seq_contains_event (Accessibility_EventTypeSeq      *type_seq,
+				  const Accessibility_DeviceEvent *event)
 {
   gint i;
   gint len;
@@ -709,10 +954,10 @@
   for (i = 0; i < len; ++i)
     {
 #ifdef SPI_DEBUG	    
-      g_print ("type_seq[%d] = %d; key event type = %d\n", i,
-	       (int) type_seq->_buffer[i], (int) key_event->type);
+      g_print ("type_seq[%d] = %d; event type = %d\n", i,
+	       (int) type_seq->_buffer[i], (int) event->type);
 #endif      
-      if (type_seq->_buffer[i] == (CORBA_long) key_event->type)
+      if (type_seq->_buffer[i] == (CORBA_long) event->type)
         {
           return TRUE;
 	}
@@ -728,7 +973,7 @@
 {
   if ((key_event->modifiers == (CORBA_unsigned_short) (listener->mask & 0xFFFF)) &&
        spi_key_set_contains_key (listener->keys, key_event) &&
-       spi_key_eventtype_seq_contains_event (listener->typeseq, key_event) && 
+       spi_eventtype_seq_contains_event (listener->listener.typeseq, key_event) && 
       (is_system_global == listener->mode->global))
     {
       return TRUE;
@@ -1058,7 +1303,7 @@
 spi_device_event_controller_object_finalize (GObject *object)
 {
   SpiDEController *controller;
-
+  DEControllerPrivateData *private;
   controller = SPI_DEVICE_EVENT_CONTROLLER (object);
 
 #ifdef SPI_DEBUG
@@ -1067,7 +1312,10 @@
   /* disconnect any special listeners, get rid of outstanding keygrabs */
   XUngrabKey (spi_get_display (), AnyKey, AnyModifier, DefaultRootWindow (spi_get_display ()));
 
-  g_free (g_object_get_data (G_OBJECT (controller), "spi-dec-private"));
+  private = g_object_get_data (G_OBJECT (controller), "spi-dec-private");
+  if (private->xkb_desc)
+	  XkbFreeKeyboard (private->xkb_desc, 0, True);
+  g_free (private);
   spi_device_event_controller_parent_class->finalize (object);
 }
 
@@ -1080,7 +1328,7 @@
 				  const Accessibility_DeviceEventListener l,
 				  const Accessibility_KeySet             *keys,
 				  const Accessibility_ControllerEventMask mask,
-				  const Accessibility_KeyEventTypeSeq    *type,
+				  const Accessibility_EventTypeSeq       *type,
 				  const Accessibility_EventListenerMode  *mode,
 				  CORBA_Environment                      *ev)
 {
@@ -1097,6 +1345,25 @@
 }
 
 
+/*
+ * CORBA Accessibility::DEController::registerDeviceEventListener
+ *     method implementation
+ */
+static CORBA_boolean
+impl_register_device_listener (PortableServer_Servant                  servant,
+			       const Accessibility_DeviceEventListener l,
+			       const Accessibility_EventTypeSeq       *event_types,
+			       CORBA_Environment                      *ev)
+{
+  SpiDEController *controller = SPI_DEVICE_EVENT_CONTROLLER (
+	  bonobo_object_from_servant (servant));
+  DEControllerListener *dec_listener;
+
+  dec_listener = spi_dec_listener_new (l, event_types, ev);
+  return spi_controller_register_device_listener (
+	  controller, (DEControllerListener *) dec_listener, ev);
+}
+
 typedef struct {
 	CORBA_Environment       *ev;
 	DEControllerKeyListener *key_listener;
@@ -1137,6 +1404,16 @@
   return SPI_RE_ENTRANT_CONTINUE;
 }
 
+/* XXX FIXME: can we do this more easily? */
+static void
+spi_deregister_controller_device_listener (SpiDEController            *controller,
+					   DEControllerListener *listener,
+					   CORBA_Environment          *ev)
+{
+  if (listener->type == SPI_DEVICE_TYPE_MOUSE) 
+    controller->mouse_listeners = 
+      g_list_remove (controller->mouse_listeners, listener);   
+}
 
 static void
 spi_deregister_controller_key_listener (SpiDEController            *controller,
@@ -1171,7 +1448,7 @@
 				    const Accessibility_DeviceEventListener l,
 				    const Accessibility_KeySet             *keys,
 				    const Accessibility_ControllerEventMask mask,
-				    const Accessibility_KeyEventTypeSeq    *type,
+				    const Accessibility_EventTypeSeq       *type,
 				    CORBA_Environment                      *ev)
 {
   DEControllerKeyListener  *key_listener;
@@ -1191,26 +1468,48 @@
   spi_dec_key_listener_free (key_listener, ev);
 }
 
+/*
+ * CORBA Accessibility::DEController::deregisterDeviceEventListener
+ *     method implementation
+ */
+static void
+impl_deregister_device_listener (PortableServer_Servant                  servant,
+				 const Accessibility_DeviceEventListener l,
+				 const Accessibility_EventTypeSeq       *event_types,
+				 CORBA_Environment                      *ev)
+{
+  SpiDEController *controller;
+  DEControllerListener *listener = 
+          spi_dec_listener_new (l, event_types, ev);
+
+  controller = SPI_DEVICE_EVENT_CONTROLLER (bonobo_object (servant));
+
+  spi_deregister_controller_device_listener (controller, listener, ev);
+
+  bonobo_object_release_unref (listener->object, ev);
+
+}
+
 static unsigned int dec_xkb_get_slowkeys_delay (SpiDEController *controller)
 {
-	unsigned int retval = 0;
+  unsigned int retval = 0;
+  DEControllerPrivateData *priv = (DEControllerPrivateData *)
+	  g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);
 #ifdef HAVE_XKB
 #ifdef XKB_HAS_GET_SLOW_KEYS_DELAY	
-	retval = XkbGetSlowKeysDelay (spi_get_display (),
-				      XkbUseCoreKbd, &bounce_delay);
+  retval = XkbGetSlowKeysDelay (spi_get_display (),
+				XkbUseCoreKbd, &bounce_delay);
 #else
-	XkbDescPtr xkb = XkbGetMap (spi_get_display (), 0, XkbUseCoreKbd);
-	if (!(xkb == (XkbDescPtr) BadAlloc || xkb == NULL))
-	{
-		Status s = XkbGetControls (spi_get_display (),
-					   XkbAllControlsMask, xkb);
-		if (s == Success)
-		{
-			if (xkb->ctrls->enabled_ctrls & XkbSlowKeysMask)
-				retval = xkb->ctrls->slow_keys_delay;
-		}
-		XkbFreeKeyboard (xkb, XkbAllControlsMask, True);
+  if (!(priv->xkb_desc == (XkbDescPtr) BadAlloc || priv->xkb_desc == NULL))
+    {
+      Status s = XkbGetControls (spi_get_display (),
+				 XkbAllControlsMask, priv->xkb_desc);
+      if (s == Success)
+        {
+	 if (priv->xkb_desc->ctrls->enabled_ctrls & XkbSlowKeysMask)
+		 retval = priv->xkb_desc->ctrls->slow_keys_delay;
 	}
+    }
 #endif
 #endif
 #ifdef SPI_XKB_DEBUG
@@ -1221,30 +1520,30 @@
 
 static unsigned int dec_xkb_get_bouncekeys_delay (SpiDEController *controller)
 {
-	unsigned int retval = 0;
+  unsigned int retval = 0;
+  DEControllerPrivateData *priv = (DEControllerPrivateData *)
+	  g_object_get_qdata (G_OBJECT (controller), spi_dec_private_quark);
 #ifdef HAVE_XKB
 #ifdef XKB_HAS_GET_BOUNCE_KEYS_DELAY	
-	retval = XkbGetBounceKeysDelay (spi_get_display (),
-					XkbUseCoreKbd, &bounce_delay);
+  retval = XkbGetBounceKeysDelay (spi_get_display (),
+				  XkbUseCoreKbd, &bounce_delay);
 #else
-	XkbDescPtr xkb = XkbGetMap (spi_get_display (), 0, XkbUseCoreKbd);
-	if (!(xkb == (XkbDescPtr) BadAlloc || xkb == NULL))
-	{
-		Status s = XkbGetControls (spi_get_display (),
-					   XkbAllControlsMask, xkb);
-		if (s == Success)
-		{
-			if (xkb->ctrls->enabled_ctrls & XkbBounceKeysMask)
-				retval = xkb->ctrls->debounce_delay;
-		}
-		XkbFreeKeyboard (xkb, XkbAllControlsMask, True);
+  if (!(priv->xkb_desc == (XkbDescPtr) BadAlloc || priv->xkb_desc == NULL))
+    {
+      Status s = XkbGetControls (spi_get_display (),
+				 XkbAllControlsMask, priv->xkb_desc);
+      if (s == Success)
+        {
+	  if (priv->xkb_desc->ctrls->enabled_ctrls & XkbBounceKeysMask)
+		  retval = priv->xkb_desc->ctrls->debounce_delay;
 	}
+    }
 #endif
 #endif
 #ifdef SPI_XKB_DEBUG
-	fprintf (stderr, "BounceKeys delay: %d\n", (int) retval);
+  fprintf (stderr, "BounceKeys delay: %d\n", (int) retval);
 #endif
-	return retval;
+  return retval;
 }
 
 static gboolean
@@ -1499,15 +1798,21 @@
 	
   epv->registerKeystrokeListener   = impl_register_keystroke_listener;
   epv->deregisterKeystrokeListener = impl_deregister_keystroke_listener;
+  epv->registerDeviceEventListener = impl_register_device_listener;
+  epv->deregisterDeviceEventListener = impl_deregister_device_listener;
   epv->generateKeyboardEvent       = impl_generate_keyboard_event;
   epv->generateMouseEvent          = impl_generate_mouse_event;
   epv->notifyListenersSync         = impl_notify_listeners_sync;
   epv->notifyListenersAsync        = impl_notify_listeners_async;
+
+  if (!spi_dec_private_quark)
+	  spi_dec_private_quark = g_quark_from_static_string ("spi-dec-private");
 }
 
 static void
 spi_device_event_controller_init (SpiDEController *device_event_controller)
 {
+  DEControllerPrivateData *private;	
   device_event_controller->key_listeners   = NULL;
   device_event_controller->mouse_listeners = NULL;
   device_event_controller->keygrabs_list   = NULL;
@@ -1519,6 +1824,13 @@
    */
   gdk_init (NULL, NULL);
   
+  private = g_new0 (DEControllerPrivateData, 1);
+  gettimeofday (&private->last_press_time, NULL);
+  gettimeofday (&private->last_release_time, NULL);
+  g_object_set_qdata (G_OBJECT (device_event_controller),
+		      spi_dec_private_quark,
+		      private);
+  
   spi_controller_register_with_devices (device_event_controller);
 }
 
@@ -1542,8 +1854,6 @@
   is_consumed = spi_controller_notify_keylisteners (
 	  controller, &key_event, CORBA_TRUE, &ev);
 
-  CORBA_exception_free (&ev);
-
   if (is_consumed)
     {
       XAllowEvents (spi_get_display (), AsyncKeyboard, CurrentTime);
@@ -1564,14 +1874,6 @@
   retval->registry = SPI_REGISTRY (bonobo_object_ref (
 	  BONOBO_OBJECT (registry)));
 
-  private = g_new0 (DEControllerPrivateData, 1);
-  gettimeofday (&private->last_press_time, NULL);
-  gettimeofday (&private->last_release_time, NULL);
-  if (!spi_dec_private_quark)
-	  spi_dec_private_quark = g_quark_from_static_string ("spi-dec-private");
-  g_object_set_qdata (G_OBJECT (retval),
-		      spi_dec_private_quark,
-		      private);
   spi_dec_init_mouse_listener (registry);
   /* TODO: kill mouse listener on finalize */  
   return retval;
Index: registryd/deviceeventcontroller.h
===================================================================
RCS file: /cvs/gnome/at-spi/registryd/deviceeventcontroller.h,v
retrieving revision 1.13
diff -u -r1.13 deviceeventcontroller.h
--- registryd/deviceeventcontroller.h	21 Oct 2002 19:41:46 -0000	1.13
+++ registryd/deviceeventcontroller.h	14 Nov 2002 22:06:49 -0000
@@ -26,7 +26,7 @@
 
 #include <bonobo/bonobo-object.h>
 #include <libspi/Accessibility.h>
-#include <libspi/keystrokelistener.h>
+#include <libspi/devicelistener.h>
 
 typedef struct _SpiDEController SpiDEController;
 
Index: registryd/registry.c
===================================================================
RCS file: /cvs/gnome/at-spi/registryd/registry.c,v
retrieving revision 1.51
diff -u -r1.51 registry.c
--- registryd/registry.c	3 Oct 2002 14:29:41 -0000	1.51
+++ registryd/registry.c	14 Nov 2002 22:06:50 -0000
@@ -633,6 +633,34 @@
 
 
 static void
+impl_registry_notify_event_full (PortableServer_Servant     servant,
+				 const Accessibility_Event *e,
+				 const CORBA_any           *any,
+				 CORBA_Environment         *ev)
+{
+  SpiRegistry  *registry;
+  GList       **list;
+  NotifyContext ctx;
+
+  registry = SPI_REGISTRY (bonobo_object_from_servant (servant));
+
+  parse_event_type (&ctx.etype, e->type);
+
+  list = get_listener_list (registry, ctx.etype.type_cat);
+
+  if (list)
+    {
+      ctx.ev = ev;
+      ctx.e_out = *e;
+      ctx.source = e->source;
+
+      spi_re_entrant_list_foreach (list, notify_listeners_cb, &ctx);
+    }
+
+}
+
+
+static void
 spi_registry_class_init (SpiRegistryClass *klass)
 {
   GObjectClass * object_class = (GObjectClass *) klass;
@@ -643,6 +671,7 @@
   object_class->finalize = spi_registry_object_finalize;
 
   klass->parent_class.epv.notifyEvent   = impl_registry_notify_event;
+  klass->parent_class.epv.notifyEventFull = impl_registry_notify_event_full;
   
   epv->registerApplication              = impl_accessibility_registry_register_application;
   epv->deregisterApplication            = impl_accessibility_registry_deregister_application;
Index: test/event-listener-test.c
===================================================================
RCS file: /cvs/gnome/at-spi/test/event-listener-test.c,v
retrieving revision 1.10
diff -u -r1.10 event-listener-test.c
--- test/event-listener-test.c	16 Oct 2002 14:27:06 -0000	1.10
+++ test/event-listener-test.c	14 Nov 2002 22:06:50 -0000
@@ -30,10 +30,12 @@
 static void report_event  (const AccessibleEvent *event, void *user_data);
 static void report_detail_event  (const AccessibleEvent *event, void *user_data);
 static void timing_test_event (const AccessibleEvent *event, void *user_data);
+static SPIBoolean report_mouse_event  (const AccessibleDeviceEvent *event, void *user_data);
 
 static AccessibleEventListener *generic_listener;
 static AccessibleEventListener *specific_listener;
 static AccessibleEventListener *test_listener;
+static AccessibleDeviceListener *mouse_device_listener;
 static gint n_elements_traversed = 0;
 static GTimer *timer;
 
@@ -86,6 +88,8 @@
 	  report_detail_event, NULL); 
   test_listener = SPI_createAccessibleEventListener (
 	  timing_test_event, NULL);
+  mouse_device_listener = SPI_createAccessibleDeviceListener (
+          report_mouse_event, NULL);
 
   SPI_registerGlobalEventListener (generic_listener,
 				   "focus:");
@@ -97,6 +101,8 @@
       SPI_registerGlobalEventListener (specific_listener,
 				       "mouse:abs");
   }
+  SPI_registerDeviceEventListener (mouse_device_listener, 
+				   SPI_BUTTON_PRESSED | SPI_BUTTON_RELEASED);
   SPI_registerGlobalEventListener (specific_listener,
 				   "keyboard:modifiers");
   SPI_registerGlobalEventListener (generic_listener,
@@ -251,6 +257,17 @@
   fprintf (stderr, "(detail) %s %s %d %d\n", event->type, s,
 	   event->detail1, event->detail2);
   if (s) SPI_freeString (s);
+}
+
+SPIBoolean
+report_mouse_event (const AccessibleDeviceEvent *event, void *user_data)
+{
+  fprintf (stderr, "mouse event %ld %d %x %x\n", 
+	   event->keyID, 
+	   (int) event->keycode,
+	   (unsigned) event->type,
+	   (unsigned) event->modifiers);
+  return FALSE;
 }
 
 void
Index: test/key-listener-test.c
===================================================================
RCS file: /cvs/gnome/at-spi/test/key-listener-test.c,v
retrieving revision 1.5
diff -u -r1.5 key-listener-test.c
--- test/key-listener-test.c	21 Oct 2002 19:41:46 -0000	1.5
+++ test/key-listener-test.c	14 Nov 2002 22:06:50 -0000
@@ -49,7 +49,7 @@
 int
 main (int argc, char **argv)
 {
-  char *tab_strings[1];
+  const char *tab_strings[1] = {"Tab"};
   short keycodes[] = {65, 64, 23};
   SPIBoolean retval = FALSE;
 	
@@ -65,7 +65,6 @@
   command_keyset = SPI_createAccessibleKeySet (1, "q", NULL, NULL);
   async_keyset = SPI_createAccessibleKeySet (3, NULL, keycodes, NULL);
   sync_keyset = SPI_createAccessibleKeySet (3, "def", NULL, NULL);
-  tab_strings[0] = "Tab";
   tab_keyset = SPI_createAccessibleKeySet (1,  NULL, NULL, tab_strings);
   retval = SPI_registerAccessibleKeystrokeListener(command_key_listener,
 			       		  command_keyset,
Index: test/keysynth-demo.c
===================================================================
RCS file: /cvs/gnome/at-spi/test/keysynth-demo.c,v
retrieving revision 1.18
diff -u -r1.18 keysynth-demo.c
--- test/keysynth-demo.c	13 Sep 2002 13:09:03 -0000	1.18
+++ test/keysynth-demo.c	14 Nov 2002 22:06:50 -0000
@@ -171,7 +171,6 @@
       case SCAN_LINES_DONE:
       case SCAN_KEYS_DONE:
 	  return FALSE;
-      default:
     }
   return TRUE;
 }
Index: test/test-simple.c
===================================================================
RCS file: /cvs/gnome/at-spi/test/test-simple.c,v
retrieving revision 1.30
diff -u -r1.30 test-simple.c
--- test/test-simple.c	16 Aug 2002 14:44:25 -0000	1.30
+++ test/test-simple.c	14 Nov 2002 22:06:51 -0000
@@ -129,7 +129,7 @@
 					   GTK_ICON_SIZE_LARGE_TOOLBAR);
 	test_window_add_and_show (GTK_CONTAINER (vbox), widget);
 
-	widget = g_object_new (GTK_TYPE_RANGE, NULL);
+	widget = g_object_new (GTK_TYPE_HSCALE, NULL);
 	gtk_range_set_range (GTK_RANGE (widget), 0.0, 100.0);
 	test_window_add_and_show (GTK_CONTAINER (vbox), widget);
 
@@ -157,8 +157,8 @@
 	for (i = -1; i < 1000; i++)
 		g_assert (AccessibleRole_getName (i) != NULL);
 
-	g_assert (!strcmp (AccessibleRole_getName (SPI_ROLE_FILE_CHOOSER), "file chooser"));
-	g_assert (!strcmp (AccessibleRole_getName (SPI_ROLE_RADIO_BUTTON), "radiobutton"));
+	g_assert (!strcmp (AccessibleRole_getName (SPI_ROLE_FILE_CHOOSER), "file-chooser"));
+	g_assert (!strcmp (AccessibleRole_getName (SPI_ROLE_RADIO_BUTTON), "radio-button"));
 	g_assert (!strcmp (AccessibleRole_getName (SPI_ROLE_TABLE), "table"));
 	g_assert (!strcmp (AccessibleRole_getName (SPI_ROLE_WINDOW), "window"));
 }
@@ -692,7 +692,6 @@
 static void
 test_keylisteners (void)
 {
-#ifdef BILL_MAKES_THIS_WORK_RELIABLY
 	int i;
 	AccessibleKeystroke stroke;
 	AccessibleKeystrokeListener *key_listener;
@@ -704,7 +703,7 @@
 		key_listener_cb, &stroke);
 
 	test_keyset = SPI_createAccessibleKeySet (1, "=", NULL, NULL);
-	
+
 	g_assert (SPI_registerAccessibleKeystrokeListener (
 		key_listener,
 		test_keyset,
@@ -736,7 +735,6 @@
         g_assert (SPI_generateMouseEvent (-50, -50, "rel"));		  
         g_assert (SPI_generateMouseEvent (-50, -50, "rel"));		  
         g_assert (SPI_generateMouseEvent (-1, -1, "b1c")); 
-#endif
 }
 
 int
@@ -771,6 +769,7 @@
 	win = create_test_window ();
 
 	global_listener = SPI_createAccessibleEventListener (global_listener_cb, win);
+
 	g_assert (SPI_registerGlobalEventListener (global_listener, "focus:"));
 
 	fprintf (stderr, "Waiting for focus event ...\n");
Index: test/visual-bell.c
===================================================================
RCS file: /cvs/gnome/at-spi/test/visual-bell.c,v
retrieving revision 1.1
diff -u -r1.1 visual-bell.c
--- test/visual-bell.c	21 Oct 2002 19:41:46 -0000	1.1
+++ test/visual-bell.c	14 Nov 2002 22:06:51 -0000
@@ -138,7 +138,6 @@
 				/* flash something */
 				visual_bell_notify (xkb_ev);
 				break;
-			default:
 			}
 		}
 	}


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]