[g-a-devel]new version of at-spi patch for device/mouse event listeners



Attached is a new version of this patch.  I plan to commit tomorrow if
there are no more issues.

While we're breaking internal API (since I will have to patch
java-access-bridge anyhow), should we add empty slots so that our
interfaces have at least four empty slots each?  It seems as though now
is the time, since I anticipate the 2.2 release to be the one when we
have stable clients and thus will need to meet strict bincompat
requirements going forward.

Opinions welcome on that topic, I can add a couple of slots before the
commit of this patch.  Bincompat for cspi clients should not be
affected, so the java-access-bridge is the only code that I am aware of
that would be affected by this change.

Meanwhile I will prepare a patch to add the extended event support (it
should not affect bincompat, thanks to Michael's suggestions).

regards,

Bill


Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/at-spi/ChangeLog,v
retrieving revision 1.256
diff -u -r1.256 ChangeLog
--- ChangeLog	15 Nov 2002 15:58:08 -0000	1.256
+++ ChangeLog	15 Nov 2002 20:35:33 -0000
@@ -1,3 +1,211 @@
+2002-11-15  Bill Haneman <bill haneman sun com>
+
+	* configure.in:
+	Revved to 1.1.3, interface-age=3, binary-age=3.
+	Added REBUILD macro.
+
+	* test/Makefile.am:
+	Removed accessx-gui from the tests, since we have a nice
+	keyboard accessibility capplet now :-)
+
+	* test/keysynth-demo.c:
+	(increment_scan): removed do-nothing default: case,
+	silences warning.
+
+	* test/visual-bell.c:
+	(main) : removed do-nothing default: case, 
+	silences warning.
+
+	* cspi/spi_action.c:
+	(AccessibleAction_getKeyBinding_): 
+	Documented keybinding string format.
+	FIX for bug 97916.
+
+	* cspi/spi_text.c:
+	(AccessibleText_getAttributes):
+	Documented the text attribute string format.
+	It's changed to use semicolon delimiters also,
+	to prevent clashes with CSS attributes, but the old
+	trick of looking for ", " strings will still work
+	(as unreliably as ever).  Fix for bug related to 97916.
+
+	* cspi/spi_event.c:
+	Include <cspi/bonobo/cspi-bonobo-listener.h>
+	Fixes build warning.
+	(SPI_freeAccessibleKeySet):
+	(AccessibleKeystrokeListener_addCallback):
+	(AccessibleKeystrokeListener_removeCallback):
+	Modify to use AccessibleDeviceListener API internally,
+	instead of AccessibleKeystrokeListener.
+	
+	* idl/Accessibility_Event.idl:
+	Added CORBA_any "any_data" member to Event struct.
+	Added two more empty slots to EventListener (for a total of four).
+
+	* idl/Accessibility_Accessible.idl:
+	Added four empty slots to Accessible interface.
+
+	* idl/Accessibility_Accessible.idl:
+	Added four empty slots to Accessible interface.
+
+2002-11-15  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.  Fixed memory leak and removed need to
+	allocate EventTypeSeq (thanks Michael for catching this).
+	Squashed a wayward CORBA_exception_free that shouldn't get called.
+
+	* 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:
+	(report_mouse_event):
+	New method.
+	(main):
+	Added mouse-event device listener.
+
+	* test/test-simple.c:
+	(create_test_window):
+	Fixed regression (we were instantiating a GtkRange,
+	which is now an abstract class).  Also fixed to match
+	existing AtkRole names, this seems to have changed in ATK
+	awhile ago; too late now I think, and the new
+	mechanism is at least elegant and consistent with the
+	glib enum "nick" APIs.	
+
 2002-11-15  Darren Kenny  <darren kenny sun com>
 
 	* idl/Accessibility_Relation.idl:
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	15 Nov 2002 20:35:33 -0000
@@ -2,9 +2,9 @@
 
 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_MICRO_VERSION=3
+AT_SPI_INTERFACE_AGE=0
+AT_SPI_BINARY_AGE=3
 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)
@@ -187,6 +187,15 @@
   AC_MSG_ERROR([A newer version of popt is required to build at-spi.
 You can download the latest version from ftp://ftp.rpm.org/pub/rpm/dist/rpm-4.0.x/])
 ])
+
+REBUILD=\#
+if test "x$enable_rebuilds" = "xyes" && \
+	test -n "$PERL" && \
+	$PERL -e 'exit !($] >= 5.002)' > /dev/null 2>&1 && \
+     test -n "$AWK" ; then
+  REBUILD=
+fi
+AC_SUBST(REBUILD)
 
 AC_OUTPUT([
 Makefile
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	15 Nov 2002 20:35:33 -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	15 Nov 2002 20:35:33 -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	15 Nov 2002 20:35:33 -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,14 @@
 SPIBoolean SPI_deregisterAccessibleKeystrokeListener (
 	                               AccessibleKeystrokeListener *listener,
 				       AccessibleKeyMaskType        modmask);
+
+SPIBoolean SPI_registerDeviceEventListener   (
+                                       AccessibleDeviceListener   *listener,
+				       AccessibleDeviceEventMask   eventmask,
+				       void                       *filter);
+SPIBoolean SPI_deregisterDeviceEventListener (
+				       AccessibleDeviceListener   *listener,
+				       void                       *filter);
 
 int         SPI_getDesktopCount                  (void);
 Accessible *SPI_getDesktop                       (int i);
Index: cspi/spi_action.c
===================================================================
RCS file: /cvs/gnome/at-spi/cspi/spi_action.c,v
retrieving revision 1.17
diff -u -r1.17 spi_action.c
--- cspi/spi_action.c	13 Sep 2002 13:08:58 -0000	1.17
+++ cspi/spi_action.c	15 Nov 2002 20:35:34 -0000
@@ -104,6 +104,25 @@
  *
  * Get the keybindings for the @i-th action invokable on an
  *      object implementing #AccessibleAction, if any are defined.
+ *      The keybindings string format is as follows:
+ *        there are multiple parts to a keybinding string (typically 3).
+ *        They are delimited with ";".  The first is the action's
+ *        keybinding which is usable if the object implementing the action
+ *        is currently posted to the screen, e.g. if a menu is posted 
+ *        then these keybindings for the corresponding menu-items are
+ *        available.  The second keybinding substring is the full key sequence
+ *        necessary to post the action's widget and activate it, e.g. for
+ *        a menu item such as "File->Open" it would both post the menu and
+ *        activate the item.  Thus the second keybinding string is available
+ *        during the lifetime of the containing toplevel window as a whole,
+ *        whereas the first keybinding string only works while the object
+ *        implementing AtkAction is posted.  The third (and optional)
+ *        keybinding string is the "keyboard shortcut" which invokes the 
+ *        action without posting any menus. 
+ *        Meta-keys are indicated by the conventional strings
+ *        "<Control>", "<Alt>", "<Shift>", "<Mod2>",
+ *        etc. (we use the same string as gtk_accelerator_name() in 
+ *        gtk+-2.X.
  *
  * Returns: a UTF-8 string which can be parsed to determine the @i-th
  *       invokable action's keybindings.
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	15 Nov 2002 20:35:34 -0000
@@ -22,8 +22,7 @@
  */
 
 #include <cspi/spi-private.h>
-
-
+#include <cspi/bonobo/cspi-bonobo-listener.h>
 
 /**
  * SPI_freeAccessibleKeySet:
@@ -198,10 +197,10 @@
 SPI_createAccessibleKeystrokeListener (AccessibleKeystrokeListenerCB callback,
 				       void                         *user_data)
 {
-  AccessibleKeystrokeListener *listener = cspi_keystroke_listener_new ();
+  AccessibleDeviceListener *listener = cspi_device_listener_new ();
   if (callback)
     {
-      AccessibleKeystrokeListener_addCallback (listener, callback, user_data);
+      AccessibleDeviceListener_addCallback (listener, callback, user_data);
     }
   return listener;
 }
@@ -222,7 +221,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 +239,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 +252,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	15 Nov 2002 20:35:34 -0000
@@ -337,6 +337,7 @@
   Accessibility_ControllerEventMask   controller_event_mask;
   Accessibility_DeviceEventController device_event_controller;
   Accessibility_EventListenerMode     listener_mode;
+  Accessibility_KeyEventType          key_event_types [2];
   SPIBoolean                          retval = FALSE;
 
   if (!listener)
@@ -375,20 +376,8 @@
     }
 	
   /* copy the event filter values from the C api into the CORBA KeyEventTypeSeq */
-  mask = 1;
-  i = 0;
-  do
-    {
-      if (mask & eventmask)
-        {
-          ++i; 
-	}
-      mask <<= 1;
-    }
-  while (mask & 0xFFFF);
-  
-  key_events._buffer = Accessibility_KeyEventTypeSeq_allocbuf (i);
   i = 0;
+  key_events._buffer = key_event_types;
   if (eventmask & SPI_KEY_PRESSED)
     {
       key_events._buffer[i++] = Accessibility_KEY_PRESSED;
@@ -417,6 +406,8 @@
     &listener_mode,
     cspi_ev ());
 
+  CORBA_free (&key_set);
+
   cspi_return_val_if_ev ("registering keystroke listener", FALSE);
 
   cspi_release_unref (device_event_controller);
@@ -469,6 +460,111 @@
     &key_set,
     controller_event_mask,
     &key_events,
+    cspi_ev ());
+
+  cspi_release_unref (device_event_controller);
+
+  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.).
+ *             
+ * 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_DeviceEventController device_event_controller;
+  SPIBoolean                          retval = FALSE;
+  Accessibility_EventTypeSeq          event_types;
+  Accessibility_EventType             event_type_buffer[2];
+  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 */
+  
+  event_types._buffer = event_type_buffer;
+  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,
+				   void                     *filter)
+{
+  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);
Index: cspi/spi_text.c
===================================================================
RCS file: /cvs/gnome/at-spi/cspi/spi_text.c,v
retrieving revision 1.20
diff -u -r1.20 spi_text.c
--- cspi/spi_text.c	13 Sep 2002 13:08:59 -0000	1.20
+++ cspi/spi_text.c	15 Nov 2002 20:35:35 -0000
@@ -174,10 +174,14 @@
  *
  * Get the attributes applied to a range of text from an #AccessibleText
  *          object, and the bounds of the range.
+ *          The text attributes correspond to CSS attributes where possible,
+ *          keys and values are delimited from one another via ":", and
+ *          the delimiter between key/value pairs is ";". Thus 
+ *          "font-size:10;foreground-color:0,0,0" would be a valid
+ *          return string.
  *
  * Returns: a text string describing the attributes occurring within the
- *          attribute run containing @offset, encoded as UTF-8 and
- *          delimited by ':'
+ *          attribute run containing @offset, encoded as UTF-8.
  **/
 char *
 AccessibleText_getAttributes (AccessibleText *obj,
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	15 Nov 2002 20:35:35 -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	15 Nov 2002 20:35:35 -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	15 Nov 2002 20:35:35 -0000
@@ -83,13 +83,11 @@
 </para>
 
 
-<!-- ##### ENUM AccessibleKeyEventType ##### -->
+<!-- ##### TYPEDEF AccessibleKeyEventType ##### -->
 <para>
 
 </para>
 
- SPI_KEY_PRESSED: 
- SPI_KEY_RELEASED: 
 
 <!-- ##### ENUM AccessibleKeyListenerSyncType ##### -->
 <para>
Index: idl/Accessibility_Accessible.idl
===================================================================
RCS file: /cvs/gnome/at-spi/idl/Accessibility_Accessible.idl,v
retrieving revision 1.12
diff -u -r1.12 Accessibility_Accessible.idl
--- idl/Accessibility_Accessible.idl	12 Dec 2001 00:28:51 -0000	1.12
+++ idl/Accessibility_Accessible.idl	15 Nov 2002 20:35:35 -0000
@@ -124,6 +124,11 @@
      * Returns: a @StateSet encapsulating the currently true states of the object.
      **/
     StateSet	getState ();
+
+    void        unImplemented ();
+    void        unImplemented2 ();
+    void        unImplemented3 ();
+    void        unImplemented4 ();
   };
 };
 
Index: idl/Accessibility_Application.idl
===================================================================
RCS file: /cvs/gnome/at-spi/idl/Accessibility_Application.idl,v
retrieving revision 1.10
diff -u -r1.10 Accessibility_Application.idl
--- idl/Accessibility_Application.idl	11 Dec 2001 16:56:15 -0000	1.10
+++ idl/Accessibility_Application.idl	15 Nov 2002 20:35:35 -0000
@@ -99,6 +99,11 @@
      * Returns: %true if the request succeeded, %false otherwise.
      **/
     boolean       resume ();
+
+    void          unImplemented_ ();
+    void          unImplemented2_ ();
+    void          unImplemented3_ ();
+    void          unImplemented4_ ();
   };
 };
 
Index: idl/Accessibility_Desktop.idl
===================================================================
RCS file: /cvs/gnome/at-spi/idl/Accessibility_Desktop.idl,v
retrieving revision 1.6
diff -u -r1.6 Accessibility_Desktop.idl
--- idl/Accessibility_Desktop.idl	1 Jan 2002 22:35:29 -0000	1.6
+++ idl/Accessibility_Desktop.idl	15 Nov 2002 20:35:35 -0000
@@ -37,8 +37,8 @@
 	   *
 	   * placeholders for future expansion.
 	   */
-	  void unImplemented ();
-	  void unImplemented2 ();
+	  void unImplemented_ ();
+	  void unImplemented2_ ();
   };
 };
 
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	15 Nov 2002 20:35:35 -0000
@@ -2,7 +2,7 @@
  * AT-SPI - Assistive Technology Service Provider Interface 
  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
  *
- * Copyright 2001 Sun Microsystems Inc.
+ * Copyright 2001, 2002 Sun Microsystems Inc.
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Library General Public
@@ -30,14 +30,19 @@
   interface Accessible;
 
   struct Event {
-    string type;
+    string     type;
     Accessible source;
-    long detail1;
-    long detail2;
+    long       detail1;
+    long       detail2;
+    any        any_data;
   };
 
   interface EventListener : Bonobo::Unknown {
     void notifyEvent (in Event e);
+    void unImplemented_ ();
+    void unImplemented2_ ();
+    void unImplemented3_ ();
+    void unImplemented4_ ();
   };
 };
 
Index: idl/Accessibility_Hypertext.idl
===================================================================
RCS file: /cvs/gnome/at-spi/idl/Accessibility_Hypertext.idl,v
retrieving revision 1.4
diff -u -r1.4 Accessibility_Hypertext.idl
--- idl/Accessibility_Hypertext.idl	1 Jan 2002 22:35:29 -0000	1.4
+++ idl/Accessibility_Hypertext.idl	15 Nov 2002 20:35:36 -0000
@@ -28,5 +28,9 @@
     long getNLinks ();
     Hyperlink getLink (in long linkIndex);
     long getLinkIndex (in long characterIndex);
+    void unImplemented ();
+    void unImplemented2 ();
+    void unImplemented3 ();
+    void unImplemented4 ();
   };
 };
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	15 Nov 2002 20:35:36 -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,10 +211,15 @@
   };	
 
   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);
+        void    unImplemented__ ();
+        void    unImplemented_2_ ();
+        void    unImplemented_3_ ();
+        void    unImplemented_4_ ();
   };
 
   interface DeviceEventController : Bonobo::Unknown {
@@ -254,6 +262,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	15 Nov 2002 20:35:36 -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	15 Nov 2002 20:35:36 -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	15 Nov 2002 20:35:36 -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: libspi/text.c
===================================================================
RCS file: /cvs/gnome/at-spi/libspi/text.c,v
retrieving revision 1.16
diff -u -r1.16 text.c
--- libspi/text.c	13 Sep 2002 13:09:01 -0000	1.16
+++ libspi/text.c	15 Nov 2002 20:35:37 -0000
@@ -212,7 +212,7 @@
       tmp = g_strdup_printf ("%s%s:%s%s",
 			     ((GSList *)(set) == cur_attr) ? "" : " ",
 			     at->name, at->value,
-			     (cur_attr->next) ? ", " : "");
+			     (cur_attr->next) ? ";" : "");
       tmp2 = g_strconcat (attributes, tmp, NULL);
       g_free (tmp);
       g_free (attributes);
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	15 Nov 2002 20:35:38 -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,32 @@
 				   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);
+			  CORBA_free (mouse_e.event_string);
+
 			  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 +351,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 +366,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 +375,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 +392,29 @@
   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 +424,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 +435,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,11 +448,20 @@
 }
 
 static void
-spi_dec_key_listener_free (DEControllerKeyListener *key_listener,
-			   CORBA_Environment       *ev)
+spi_listener_clone_free (DEControllerListener *clone, CORBA_Environment *ev)
 {
-  bonobo_object_release_unref (key_listener->listener.object, ev);
-  spi_key_listener_data_free (key_listener, ev);
+  CORBA_Object_release (clone->object, ev);
+  CORBA_free (clone->typeseq);
+  g_free (clone);
+}
+
+static void
+spi_dec_listener_free (DEControllerListener    *listener,
+		       CORBA_Environment       *ev)
+{
+  bonobo_object_release_unref (listener->object, ev);
+  if (listener->type == SPI_DEVICE_TYPE_KBD) 
+    spi_key_listener_data_free ((DEControllerKeyListener *) listener, ev);
 }
 
 static void
@@ -527,22 +595,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);
+        }
+      
+      spi_listener_clone_free ((DEControllerListener *) l2->data, 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 +722,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);
+  CORBA_free (mouse_e.event_string);
+
   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 +774,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 +858,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 +933,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 +956,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 +975,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;
@@ -795,14 +1042,14 @@
 	  CORBA_exception_free (ev);
         }
 
-      CORBA_Object_release (ls, ev);
+      spi_key_listener_clone_free (key_listener, ev);
     }
 
   for (; l2; l2 = l2->next)
     {
       DEControllerKeyListener *key_listener = l2->data;	    
       spi_key_listener_clone_free (key_listener, ev);
-      /* clone doesn't have its own ref, so don't use spi_key_listener_free */
+      /* clone doesn't have its own ref, so don't use spi_dec_listener_free */
     }
 
   g_slist_free (notify);
@@ -1058,7 +1305,7 @@
 spi_device_event_controller_object_finalize (GObject *object)
 {
   SpiDEController *controller;
-
+  DEControllerPrivateData *private;
   controller = SPI_DEVICE_EVENT_CONTROLLER (object);
 
 #ifdef SPI_DEBUG
@@ -1067,7 +1314,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 +1330,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,23 +1347,42 @@
 }
 
 
+/*
+ * 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;
-} RemoveKeyListenerClosure;
+	DEControllerListener    *listener;
+} RemoveListenerClosure;
 
 static SpiReEntrantContinue
-remove_key_listener_cb (GList * const *list,
-			gpointer       user_data)
+remove_listener_cb (GList * const *list,
+		    gpointer       user_data)
 {
-  DEControllerKeyListener  *key_listener = (*list)->data;
-  RemoveKeyListenerClosure *ctx = user_data;
+  DEControllerListener  *listener = (*list)->data;
+  RemoveListenerClosure *ctx = user_data;
 
-  if (CORBA_Object_is_equivalent (ctx->key_listener->listener.object,
-				  key_listener->listener.object, ctx->ev))
+  if (CORBA_Object_is_equivalent (ctx->listener->object,
+				  listener->object, ctx->ev))
     {
       spi_re_entrant_list_delete_link (list);
-      spi_dec_key_listener_free (key_listener, ctx->ev);
+      spi_dec_listener_free (listener, ctx->ev);
     }
 
   return SPI_RE_ENTRANT_CONTINUE;
@@ -1124,29 +1393,39 @@
 		      gpointer       user_data)
 {
   DEControllerKeyListener  *key_listener = (*list)->data;
-  RemoveKeyListenerClosure *ctx = user_data;
+  RemoveListenerClosure    *ctx = user_data;
 
-  if (CORBA_Object_is_equivalent (ctx->key_listener->listener.object,
+  if (CORBA_Object_is_equivalent (ctx->listener->object,
 				  key_listener->listener.object, ctx->ev))
     {
       /* TODO: FIXME aggregate keys in case the listener is registered twice */
-      CORBA_free (ctx->key_listener->keys);	    
-      ctx->key_listener->keys = ORBit_copy_value (key_listener->keys, TC_Accessibility_KeySet);
+      DEControllerKeyListener *ctx_key_listener = 
+	(DEControllerKeyListener *) ctx->listener; 
+      CORBA_free (ctx_key_listener->keys);	    
+      ctx_key_listener->keys = ORBit_copy_value (key_listener->keys, TC_Accessibility_KeySet);
     }
 
   return SPI_RE_ENTRANT_CONTINUE;
 }
 
+static void
+spi_deregister_controller_device_listener (SpiDEController            *controller,
+					   DEControllerListener *listener,
+					   CORBA_Environment          *ev)
+{
+  spi_re_entrant_list_foreach (&controller->mouse_listeners,
+			       remove_listener_cb, listener);
+}
 
 static void
 spi_deregister_controller_key_listener (SpiDEController            *controller,
 					DEControllerKeyListener    *key_listener,
 					CORBA_Environment          *ev)
 {
-  RemoveKeyListenerClosure  ctx;
+  RemoveListenerClosure  ctx;
 
   ctx.ev = ev;
-  ctx.key_listener = key_listener;
+  ctx.listener = (DEControllerListener *) key_listener;
 
   /* special case, copy keyset from existing controller list entry */
   if (key_listener->keys->_length == 0) 
@@ -1158,7 +1437,7 @@
   spi_controller_deregister_global_keygrabs (controller, key_listener);
 
   spi_re_entrant_list_foreach (&controller->key_listeners,
-				remove_key_listener_cb, &ctx);
+				remove_listener_cb, &ctx);
 
 }
 
@@ -1171,7 +1450,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;
@@ -1188,29 +1467,50 @@
 
   spi_deregister_controller_key_listener (controller, key_listener, ev);
 
-  spi_dec_key_listener_free (key_listener, ev);
+  spi_dec_listener_free ((DEControllerListener *) 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);
+
+  spi_dec_listener_free (listener, 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 +1521,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 +1799,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 +1825,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 +1855,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 +1875,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	15 Nov 2002 20:35:38 -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	15 Nov 2002 20:35:39 -0000
@@ -631,7 +631,6 @@
 
 }
 
-
 static void
 spi_registry_class_init (SpiRegistryClass *klass)
 {
Index: test/Makefile.am
===================================================================
RCS file: /cvs/gnome/at-spi/test/Makefile.am,v
retrieving revision 1.18
diff -u -r1.18 Makefile.am
--- test/Makefile.am	21 Oct 2002 19:41:46 -0000	1.18
+++ test/Makefile.am	15 Nov 2002 20:35:39 -0000
@@ -1,6 +1,6 @@
 NULL=
 
-noinst_PROGRAMS = test-simple at app simple-at stress-test keysynth-demo accessx-gui key-listener-test event-listener-test screen-review-test visual-bell
+noinst_PROGRAMS = test-simple at app simple-at stress-test keysynth-demo key-listener-test event-listener-test screen-review-test visual-bell
 
 key_listener_test_SOURCES = key-listener-test.c
 
@@ -19,8 +19,6 @@
 simple_at_SOURCES = simple-at.c 
 
 keysynth_demo_SOURCES = keysynth-demo.c 
-
-accessx_gui_SOURCES = accessx-gui.c 
 
 test_simple_SOURCES = test-simple.c 
 
Index: test/event-listener-test.c
===================================================================
RCS file: /cvs/gnome/at-spi/test/event-listener-test.c,v
retrieving revision 1.11
diff -u -r1.11 event-listener-test.c
--- test/event-listener-test.c	15 Nov 2002 15:58:10 -0000	1.11
+++ test/event-listener-test.c	15 Nov 2002 20:35:39 -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,9 @@
       SPI_registerGlobalEventListener (specific_listener,
 				       "mouse:abs");
   }
+  SPI_registerDeviceEventListener (mouse_device_listener, 
+				   SPI_BUTTON_PRESSED | SPI_BUTTON_RELEASED,
+				   NULL);
   SPI_registerGlobalEventListener (specific_listener,
 				   "keyboard:modifiers");
   SPI_registerGlobalEventListener (generic_listener,
@@ -253,6 +260,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	15 Nov 2002 20:35:39 -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	15 Nov 2002 20:35:40 -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	15 Nov 2002 20:35:40 -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	15 Nov 2002 20:35:40 -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]