From: billh Date: Sun, 17 Nov 2002 13:54:00 +0000 (+0000) Subject: Fix for 95827, adds API for registering "AccessibleDeviceListeners" X-Git-Tag: AT_SPI2_ATK_2_12_0~1312 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git;a=commitdiff_plain;h=0636c73a13c54781dc05b050af5f7f171b0194f9 Fix for 95827, adds API for registering "AccessibleDeviceListeners" which can receive (and potentially, consume) device events such as mouse button events, etc. Necessary for GOK and other assistive technologies. Added a couple of slots to epvs in IDL, so this breaks internal bincompat. CSPI bincompat not affected. git-svn-id: http://svn.gnome.org/svn/at-spi/trunk@360 e2bd861d-eb25-0410-b326-f6ed22b6b98c --- diff --git a/ChangeLog b/ChangeLog index c294176..9725c93 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,210 @@ +2002-11-17 Bill Haneman + + * 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 + Fixes build warning. + (SPI_freeAccessibleKeySet): + (AccessibleKeystrokeListener_addCallback): + (AccessibleKeystrokeListener_removeCallback): + Modify to use AccessibleDeviceListener API internally, + instead of AccessibleKeystrokeListener. + + * idl/Accessibility_Event.idl: + 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 + + * 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 * idl/Accessibility_Relation.idl: diff --git a/configure.in b/configure.in index 47353c3..b7aff56 100644 --- a/configure.in +++ b/configure.in @@ -2,9 +2,9 @@ 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_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) @@ -188,6 +188,15 @@ AC_TRY_CPP([#include 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 libspi-1.0.pc diff --git a/cspi/bonobo/cspi-bonobo-listener.c b/cspi/bonobo/cspi-bonobo-listener.c index d113597..9a5eb32 100644 --- a/cspi/bonobo/cspi-bonobo-listener.c +++ b/cspi/bonobo/cspi-bonobo-listener.c @@ -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 @@ typedef struct 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 @@ cspi_event_listener_remove_cb (AccessibleEventListener *al, 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_BUTTON_PRESSED_EVENT: + anevent.type = SPI_BUTTON_PRESSED; break; - case Accessibility_KEY_RELEASED: - akeystroke.type = SPI_KEY_RELEASED; + 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 @@ cspi_key_event (SpiKeystrokeListener *listener, } 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 @@ cspi_keystroke_listener_finalize (GObject *object) 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 @@ cspi_event_listener_unref (AccessibleEventListener *listener) } void -cspi_keystroke_listener_unref (AccessibleKeystrokeListener *listener) +cspi_device_listener_unref (AccessibleDeviceListener *listener) { bonobo_object_unref (BONOBO_OBJECT (listener)); } @@ -323,7 +314,7 @@ cspi_event_listener_get_corba (AccessibleEventListener *listener) } CORBA_Object -cspi_keystroke_listener_get_corba (AccessibleKeystrokeListener *listener) +cspi_device_listener_get_corba (AccessibleDeviceListener *listener) { return BONOBO_OBJREF (listener); } diff --git a/cspi/bonobo/cspi-bonobo-listener.h b/cspi/bonobo/cspi-bonobo-listener.h index 58c818b..8dbcf9e 100644 --- a/cspi/bonobo/cspi-bonobo-listener.h +++ b/cspi/bonobo/cspi-bonobo-listener.h @@ -24,7 +24,7 @@ #define __SPI_LISTENER_IMP_H__ #include -#include +#include #include #include @@ -44,19 +44,20 @@ typedef SpiEventListenerClass CSpiEventListenerClass; 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 diff --git a/cspi/spi-impl.h b/cspi/spi-impl.h index d71a822..d29d014 100644 --- a/cspi/spi-impl.h +++ b/cspi/spi-impl.h @@ -52,6 +52,7 @@ typedef Accessible AccessibilityRegistry; typedef void AccessibleEventListener; typedef void AccessibleKeystrokeListener; +typedef void AccessibleDeviceListener; typedef unsigned int SPIBoolean; diff --git a/cspi/spi-listener.h b/cspi/spi-listener.h index c942179..63384f6 100644 --- a/cspi/spi-listener.h +++ b/cspi/spi-listener.h @@ -42,19 +42,24 @@ typedef struct { 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. @@ -69,6 +74,8 @@ typedef void (*AccessibleEventListenerCB) (const AccessibleEvent * void *user_data); typedef SPIBoolean (*AccessibleKeystrokeListenerCB) (const AccessibleKeystroke *stroke, void *user_data); +typedef SPIBoolean (*AccessibleDeviceListenerCB) (const AccessibleDeviceEvent *stroke, + void *user_data); #ifdef __cplusplus } diff --git a/cspi/spi.h b/cspi/spi.h index 5e5e0f7..3105446 100644 --- a/cspi/spi.h +++ b/cspi/spi.h @@ -100,6 +100,7 @@ typedef enum { } AccessibleKeyListenerSyncType; typedef unsigned long AccessibleKeyEventMask; +typedef unsigned long AccessibleDeviceEventMask; /** * AccessibleComponentLayer: @@ -155,8 +156,8 @@ typedef struct _AccessibleKeySet **/ #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 @@ SPIBoolean AccessibleEventListener_removeCallback ( 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 @@ SPIBoolean AccessibleKeystrokeListener_removeCallback ( 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 ( @@ -224,6 +240,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); int SPI_getDesktopList (Accessible ***desktop_list); diff --git a/cspi/spi_action.c b/cspi/spi_action.c index b6887e9..adfd1d1 100644 --- a/cspi/spi_action.c +++ b/cspi/spi_action.c @@ -104,6 +104,25 @@ AccessibleAction_getDescription (AccessibleAction *obj, * * 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 + * "", "", "", "", + * 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. diff --git a/cspi/spi_event.c b/cspi/spi_event.c index f36a24a..5eb5c16 100644 --- a/cspi/spi_event.c +++ b/cspi/spi_event.c @@ -22,8 +22,7 @@ */ #include - - +#include /** * SPI_freeAccessibleKeySet: @@ -198,10 +197,10 @@ AccessibleKeystrokeListener * 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 @@ AccessibleKeystrokeListener_addCallback (AccessibleKeystrokeListener *listener, 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 @@ SPIBoolean 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 @@ AccessibleKeystrokeListener_removeCallback (AccessibleKeystrokeListener *listene 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); } diff --git a/cspi/spi_registry.c b/cspi/spi_registry.c index 1adcb3c..e97ffc1 100644 --- a/cspi/spi_registry.c +++ b/cspi/spi_registry.c @@ -337,6 +337,7 @@ SPI_registerAccessibleKeystrokeListener (AccessibleKeystrokeListener *listener, 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) @@ -360,7 +361,7 @@ SPI_registerAccessibleKeystrokeListener (AccessibleKeystrokeListener *listener, key_set._buffer[i].keysym = keys->keysyms[i]; if (keys->keystrings && keys->keystrings[i]) { - key_set._buffer[i].keystring = keys->keystrings[i]; + key_set._buffer[i].keystring = CORBA_string_dup(keys->keystrings[i]); } else { @@ -375,20 +376,8 @@ SPI_registerAccessibleKeystrokeListener (AccessibleKeystrokeListener *listener, } /* 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 @@ SPI_registerAccessibleKeystrokeListener (AccessibleKeystrokeListener *listener, &listener_mode, cspi_ev ()); + CORBA_free (key_set._buffer); + cspi_return_val_if_ev ("registering keystroke listener", FALSE); cspi_release_unref (device_event_controller); @@ -477,6 +468,111 @@ SPI_deregisterAccessibleKeystrokeListener (AccessibleKeystrokeListener *listener } /** + * 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); + + return TRUE; +} + +/** * SPI_generateKeyboardEvent: * @keyval: a long integer indicating the keycode or keysym of the key event * being synthesized. diff --git a/cspi/spi_text.c b/cspi/spi_text.c index 35e33c2..32fabba 100644 --- a/cspi/spi_text.c +++ b/cspi/spi_text.c @@ -174,10 +174,14 @@ AccessibleText_getCaretOffset (AccessibleText *obj) * * 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, diff --git a/docs/reference/cspi/tmpl/spi_registry.sgml b/docs/reference/cspi/tmpl/spi_registry.sgml index 23adfde..f9cc3f7 100644 --- a/docs/reference/cspi/tmpl/spi_registry.sgml +++ b/docs/reference/cspi/tmpl/spi_registry.sgml @@ -83,13 +83,11 @@ Registry queries - + -@SPI_KEY_PRESSED: -@SPI_KEY_RELEASED: diff --git a/idl/Accessibility_Accessible.idl b/idl/Accessibility_Accessible.idl index d3e7e40..191ef7d 100644 --- a/idl/Accessibility_Accessible.idl +++ b/idl/Accessibility_Accessible.idl @@ -124,6 +124,11 @@ module Accessibility { * Returns: a @StateSet encapsulating the currently true states of the object. **/ StateSet getState (); + + void unImplemented (); + void unImplemented2 (); + void unImplemented3 (); + void unImplemented4 (); }; }; diff --git a/idl/Accessibility_Application.idl b/idl/Accessibility_Application.idl index 50482eb..e62a7b8 100644 --- a/idl/Accessibility_Application.idl +++ b/idl/Accessibility_Application.idl @@ -99,6 +99,11 @@ module Accessibility { * Returns: %true if the request succeeded, %false otherwise. **/ boolean resume (); + + void unImplemented_ (); + void unImplemented2_ (); + void unImplemented3_ (); + void unImplemented4_ (); }; }; diff --git a/idl/Accessibility_Desktop.idl b/idl/Accessibility_Desktop.idl index 7a0cfb4..69a7aa2 100644 --- a/idl/Accessibility_Desktop.idl +++ b/idl/Accessibility_Desktop.idl @@ -37,8 +37,8 @@ module Accessibility { * * placeholders for future expansion. */ - void unImplemented (); - void unImplemented2 (); + void unImplemented_ (); + void unImplemented2_ (); }; }; diff --git a/idl/Accessibility_Event.idl b/idl/Accessibility_Event.idl index ba0465c..23c66fa 100644 --- a/idl/Accessibility_Event.idl +++ b/idl/Accessibility_Event.idl @@ -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,18 @@ module Accessibility interface Accessible; struct Event { - string type; + string type; Accessible source; - long detail1; - long detail2; + long detail1; + long detail2; }; interface EventListener : Bonobo::Unknown { void notifyEvent (in Event e); + void unImplemented_ (); + void unImplemented2_ (); + void unImplemented3_ (); + void unImplemented4_ (); }; }; diff --git a/idl/Accessibility_Hypertext.idl b/idl/Accessibility_Hypertext.idl index 0b5f27e..97dc74f 100644 --- a/idl/Accessibility_Hypertext.idl +++ b/idl/Accessibility_Hypertext.idl @@ -28,5 +28,9 @@ module Accessibility { long getNLinks (); Hyperlink getLink (in long linkIndex); long getLinkIndex (in long characterIndex); + void unImplemented (); + void unImplemented2 (); + void unImplemented3 (); + void unImplemented4 (); }; }; diff --git a/idl/Accessibility_Registry.idl b/idl/Accessibility_Registry.idl index 74165cf..46fb458 100644 --- a/idl/Accessibility_Registry.idl +++ b/idl/Accessibility_Registry.idl @@ -153,6 +153,7 @@ module Accessibility { void unImplemented2 (); }; + /* Deprecated, DO NOT USE! */ enum KeyEventType { KEY_PRESSED, KEY_RELEASED @@ -160,7 +161,9 @@ module Accessibility { enum EventType { KEY_PRESSED_EVENT, - KEY_RELEASED_EVENT + KEY_RELEASED_EVENT, + BUTTON_PRESSED_EVENT, + BUTTON_RELEASED_EVENT }; enum KeySynthType { @@ -208,10 +211,15 @@ module Accessibility { }; 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 { @@ -255,6 +263,34 @@ module Accessibility { 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); oneway void notifyListenersAsync (in DeviceEvent event); diff --git a/libspi/Makefile.am b/libspi/Makefile.am index cf77e28..16848b9 100644 --- a/libspi/Makefile.am +++ b/libspi/Makefile.am @@ -24,6 +24,7 @@ libspiinclude_HEADERS = \ hyperlink.h \ hypertext.h \ image.h \ + devicelistener.h \ keystrokelistener.h \ keymasks.h \ libspi.h \ @@ -74,7 +75,7 @@ libspi_la_SOURCES = \ hyperlink.c \ hypertext.c \ image.c \ - keystrokelistener.c \ + devicelistener.c \ relation.c \ remoteobject.c \ selection.c \ diff --git a/libspi/devicelistener.c b/libspi/devicelistener.c new file mode 100644 index 0000000..cdafb85 --- /dev/null +++ b/libspi/devicelistener.c @@ -0,0 +1,146 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* devicelistener.c: implement the DeviceListener interface */ + +#include +#ifdef SPI_DEBUG +# include +#endif +#include +#include + +/* Our parent Gtk object type */ +#define PARENT_TYPE BONOBO_TYPE_OBJECT + +enum { + DEVICE_EVENT, + LAST_SIGNAL +}; +static guint signals [LAST_SIGNAL]; + +/* + * CORBA Accessibility::DeviceListener::keyEvent method implementation + */ +static CORBA_boolean +impl_device_event (PortableServer_Servant servant, + const Accessibility_DeviceEvent *key, + CORBA_Environment *ev) +{ + gboolean was_consumed = FALSE; + SpiDeviceListener *listener = SPI_DEVICE_LISTENER ( + bonobo_object_from_servant (servant)); + + g_signal_emit (G_OBJECT (listener), signals [DEVICE_EVENT], 0, key, &was_consumed); + + return was_consumed; +} + +static gboolean +boolean_handled_accumulator (GSignalInvocationHint *ihint, + GValue *return_accu, + const GValue *handler_return, + gpointer dummy) +{ + gboolean continue_emission; + gboolean signal_handled; + + signal_handled = g_value_get_boolean (handler_return); + g_value_set_boolean (return_accu, signal_handled); + continue_emission = !signal_handled; + + return continue_emission; +} + +void +marshal_BOOLEAN__POINTER (GClosure *closure, + GValue *return_value, + guint n_param_values, + const GValue *param_values, + gpointer invocation_hint, + gpointer marshal_data) +{ + typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER) (gpointer data1, + gpointer arg_1, + gpointer data2); + register GMarshalFunc_BOOLEAN__POINTER callback; + register GCClosure *cc = (GCClosure*) closure; + register gpointer data1, data2; + gboolean v_return; + + g_return_if_fail (return_value != NULL); + g_return_if_fail (n_param_values == 2); + + if (G_CCLOSURE_SWAP_DATA (closure)) + { + data1 = closure->data; + data2 = g_value_peek_pointer (param_values + 0); + } + else + { + data1 = g_value_peek_pointer (param_values + 0); + data2 = closure->data; + } + callback = (GMarshalFunc_BOOLEAN__POINTER) (marshal_data ? marshal_data : cc->callback); + + v_return = callback (data1, + g_value_get_pointer (param_values + 1), + data2); + + g_value_set_boolean (return_value, v_return); +} + +static void +spi_device_listener_class_init (SpiDeviceListenerClass *klass) +{ + POA_Accessibility_DeviceEventListener__epv *epv = &klass->epv; + + signals [DEVICE_EVENT] = g_signal_new ( + "device_event", + G_TYPE_FROM_CLASS (klass), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (SpiDeviceListenerClass, device_event), + boolean_handled_accumulator, NULL, + marshal_BOOLEAN__POINTER, + G_TYPE_BOOLEAN, 1, G_TYPE_POINTER); + + epv->notifyEvent = impl_device_event; +} + +static void +spi_device_listener_init (SpiDeviceListener *device_listener) +{ +} + +BONOBO_TYPE_FUNC_FULL (SpiDeviceListener, + Accessibility_DeviceEventListener, + BONOBO_TYPE_OBJECT, + spi_device_listener); + +SpiDeviceListener * +spi_device_listener_new (void) +{ + SpiDeviceListener *retval = g_object_new ( + SPI_DEVICE_LISTENER_TYPE, NULL); + return retval; +} diff --git a/libspi/devicelistener.h b/libspi/devicelistener.h new file mode 100644 index 0000000..9c9e40d --- /dev/null +++ b/libspi/devicelistener.h @@ -0,0 +1,59 @@ +/* + * AT-SPI - Assistive Technology Service Provider Interface + * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) + * + * Copyright 2001, 2002 Sun Microsystems Inc., + * Copyright 2001, 2002 Ximian, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#ifndef SPI_DEVICE_LISTENER_H_ +#define SPI_DEVICE_LISTENER_H_ + +#include +#include +#include +#include + +G_BEGIN_DECLS + +#define SPI_DEVICE_LISTENER_TYPE (spi_device_listener_get_type ()) +#define SPI_DEVICE_LISTENER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), SPI_DEVICE_LISTENER_TYPE, SpiDeviceListener)) +#define SPI_DEVICE_LISTENER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), SPI_DEVICE_LISTENER_TYPE, SpiDeviceListenerClass)) +#define SPI_IS_DEVICE_LISTENER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), SPI_DEVICE_LISTENER_TYPE)) +#define SPI_IS_DEVICE_LISTENER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), SPI_DEVICE_LISTENER_TYPE)) + +typedef struct _SpiDeviceListener SpiDeviceListener; + +struct _SpiDeviceListener { + BonoboObject parent; +}; + +typedef struct { + BonoboObjectClass parent_class; + POA_Accessibility_DeviceEventListener__epv epv; + + gboolean (*device_event) (SpiDeviceListener *listener, + const Accessibility_DeviceEvent *key); +} SpiDeviceListenerClass; + +GType spi_device_listener_get_type (void); +SpiDeviceListener *spi_device_listener_new (void); + +G_END_DECLS + +#endif /* DEVICE_SPI_LISTENER_H_ */ diff --git a/libspi/keystrokelistener.h b/libspi/keystrokelistener.h index e341c7e..ed2ba45 100644 --- a/libspi/keystrokelistener.h +++ b/libspi/keystrokelistener.h @@ -24,35 +24,22 @@ #ifndef SPI_KEYSTROKE_LISTENER_H_ #define SPI_KEYSTROKE_LISTENER_H_ -#include -#include -#include -#include - 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 + +#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 diff --git a/libspi/libspi.h b/libspi/libspi.h index 1bc20b7..ae47293 100644 --- a/libspi/libspi.h +++ b/libspi/libspi.h @@ -41,7 +41,7 @@ #include #include #include -#include +#include #include #include diff --git a/libspi/text.c b/libspi/text.c index 8ca561c..8aa5764 100644 --- a/libspi/text.c +++ b/libspi/text.c @@ -212,7 +212,7 @@ _string_from_attribute_set (AtkAttributeSet *set) 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); diff --git a/registryd/deviceeventcontroller.c b/registryd/deviceeventcontroller.c index 6812f5c..600c3d4 100644 --- a/registryd/deviceeventcontroller.c +++ b/registryd/deviceeventcontroller.c @@ -82,6 +82,7 @@ typedef struct { typedef struct { CORBA_Object object; SpiDeviceTypeCategory type; + Accessibility_EventTypeSeq *typeseq; } DEControllerListener; typedef struct { @@ -89,7 +90,6 @@ typedef struct { Accessibility_KeySet *keys; Accessibility_ControllerEventMask mask; - Accessibility_KeyEventTypeSeq *typeseq; Accessibility_EventListenerMode *mode; } DEControllerKeyListener; @@ -98,6 +98,13 @@ typedef struct { 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 @@ static gboolean spi_controller_register_device_listener (SpiDEController 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 @@ static gboolean 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 @@ spi_dec_poll_mouse_moved (gpointer data) 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 @@ spi_dec_init_mouse_listener (SpiRegistry *registry) 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 @@ static DEControllerKeyListener * 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 @@ spi_dec_key_listener_new (CORBA_Object l, 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 @@ spi_dec_key_listener_new (CORBA_Object l, 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 @@ spi_key_listener_clone (DEControllerKeyListener *key_listener, CORBA_Environment 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 @@ spi_key_listener_clone (DEControllerKeyListener *key_listener, CORBA_Environment 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 @@ spi_key_listener_clone_free (DEControllerKeyListener *clone, CORBA_Environment * } static void -spi_dec_key_listener_free (DEControllerKeyListener *key_listener, - CORBA_Environment *ev) +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_listener_free (DEControllerListener *listener, + CORBA_Environment *ev) { - bonobo_object_release_unref (key_listener->listener.object, ev); - spi_key_listener_data_free (key_listener, 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 @@ spi_controller_register_device_listener (SpiDEController *controller, 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 @@ spi_device_event_controller_forward_mouse_event (SpiDEController *controller, #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,67 @@ global_filter_fn (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) { 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; + 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 +857,25 @@ _spi_controller_device_error_handler (Display *display, XErrorEvent *error) 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 +932,8 @@ spi_key_set_contains_key (Accessibility_KeySet *key_set, } 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 +955,10 @@ spi_key_eventtype_seq_contains_event (Accessibility_KeyEventTypeSeq *type_seq, 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 +974,7 @@ spi_key_event_matches_listener (const Accessibility_DeviceEvent *key_event, { 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 +1041,14 @@ spi_controller_notify_keylisteners (SpiDEController *controller, 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 +1304,7 @@ static void spi_device_event_controller_object_finalize (GObject *object) { SpiDEController *controller; - + DEControllerPrivateData *private; controller = SPI_DEVICE_EVENT_CONTROLLER (object); #ifdef SPI_DEBUG @@ -1067,7 +1313,10 @@ spi_device_event_controller_object_finalize (GObject *object) /* 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 +1329,7 @@ impl_register_keystroke_listener (PortableServer_Servant servan 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 +1346,42 @@ impl_register_keystroke_listener (PortableServer_Servant servan } +/* + * 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 +1392,39 @@ copy_key_listener_cb (GList * const *list, 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 +1436,7 @@ spi_deregister_controller_key_listener (SpiDEController *controller, 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 +1449,7 @@ impl_deregister_keystroke_listener (PortableServer_Servant serv 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 +1466,50 @@ impl_deregister_keystroke_listener (PortableServer_Servant serv 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 +1520,30 @@ static unsigned int dec_xkb_get_slowkeys_delay (SpiDEController *controller) 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 @@ spi_device_event_controller_class_init (SpiDEControllerClass *klass) 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 @@ spi_device_event_controller_init (SpiDEController *device_event_controller) */ 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 @@ spi_device_event_controller_forward_key_event (SpiDEController *controller, 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 @@ spi_device_event_controller_new (SpiRegistry *registry) 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; diff --git a/registryd/deviceeventcontroller.h b/registryd/deviceeventcontroller.h index 90ebb0d..14cb16f 100644 --- a/registryd/deviceeventcontroller.h +++ b/registryd/deviceeventcontroller.h @@ -26,7 +26,7 @@ #include #include -#include +#include typedef struct _SpiDEController SpiDEController; diff --git a/registryd/registry.c b/registryd/registry.c index 558f2df..c00365a 100644 --- a/registryd/registry.c +++ b/registryd/registry.c @@ -631,7 +631,6 @@ impl_registry_notify_event (PortableServer_Servant servant, } - static void spi_registry_class_init (SpiRegistryClass *klass) { diff --git a/test/Makefile.am b/test/Makefile.am index 5a06fda..bc2c579 100644 --- a/test/Makefile.am +++ b/test/Makefile.am @@ -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 @@ -20,8 +20,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 INCLUDES = -I$(top_srcdir) \ diff --git a/test/event-listener-test.c b/test/event-listener-test.c index b22c89c..a729124 100644 --- a/test/event-listener-test.c +++ b/test/event-listener-test.c @@ -30,10 +30,12 @@ static void traverse_accessible_tree (Accessible *accessible); 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 @@ main (int argc, char **argv) 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 @@ main (int argc, char **argv) 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, @@ -255,6 +262,17 @@ report_detail_event (const AccessibleEvent *event, void *user_data) 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 timing_test_event (const AccessibleEvent *event, void *user_data) { diff --git a/test/key-listener-test.c b/test/key-listener-test.c index dc0186a..e09942a 100644 --- a/test/key-listener-test.c +++ b/test/key-listener-test.c @@ -49,7 +49,7 @@ static AccessibleKeySet *tab_keyset; 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 @@ main (int argc, char **argv) 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, diff --git a/test/keysynth-demo.c b/test/keysynth-demo.c index f5b4158..720773c 100644 --- a/test/keysynth-demo.c +++ b/test/keysynth-demo.c @@ -171,7 +171,6 @@ increment_scan (gpointer data) case SCAN_LINES_DONE: case SCAN_KEYS_DONE: return FALSE; - default: } return TRUE; } diff --git a/test/test-simple.c b/test/test-simple.c index 802a3d0..2d13812 100644 --- a/test/test-simple.c +++ b/test/test-simple.c @@ -129,7 +129,7 @@ create_test_window (void) 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 @@ test_roles (void) 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 @@ key_listener_cb (const AccessibleKeystroke *stroke, static void test_keylisteners (void) { -#ifdef BILL_MAKES_THIS_WORK_RELIABLY int i; AccessibleKeystroke stroke; AccessibleKeystrokeListener *key_listener; @@ -704,7 +703,7 @@ test_keylisteners (void) key_listener_cb, &stroke); test_keyset = SPI_createAccessibleKeySet (1, "=", NULL, NULL); - + g_assert (SPI_registerAccessibleKeystrokeListener ( key_listener, test_keyset, @@ -736,7 +735,6 @@ test_keylisteners (void) 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 @@ main (int argc, char **argv) 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"); diff --git a/test/visual-bell.c b/test/visual-bell.c index 874a4bc..d8d0f59 100755 --- a/test/visual-bell.c +++ b/test/visual-bell.c @@ -138,7 +138,6 @@ int main (int argc, char **argv) /* flash something */ visual_bell_notify (xkb_ev); break; - default: } } }