From: billh Date: Sun, 18 Nov 2001 22:51:50 +0000 (+0000) Subject: Added docs and C bindings for AccessibleStateSet and AccessibleRelationSet. X-Git-Tag: AT_SPI2_ATK_2_12_0~1535 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git;a=commitdiff_plain;h=783e63cad5945ddb6df3ee129d20d5b53c6cce04 Added docs and C bindings for AccessibleStateSet and AccessibleRelationSet. Improved listener API docs and listed legal signals (other than GTK+ signals, which are documented in GTK+ itself). C bindings documentation coverage is now 100%. Changed Registry.idl slightly, added two methods to DeviceEventController API. Some work towards non-preemptive key listeners. Fixed regression in signal connection caused by changes to Gtk+. Connected bridge to all signals, so they should be available if they are emitted. git-svn-id: http://svn.gnome.org/svn/at-spi/trunk@96 e2bd861d-eb25-0410-b326-f6ed22b6b98c --- diff --git a/ChangeLog b/ChangeLog index c523582..032a7db 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,73 @@ +2001-18-11 Bill Haneman + + * libspi/spi_accessible.c: Added docs and C bindings for + AccessibleStateSet. (No implementations yet). Documentation + coverage for C bindings now 100%. Made docs for event listeners + more explicit. + + * idl/Registry.idl: + Added methods + boolean notifyListenersSync (in DeviceEventListener listener, + in DeviceEvent event); + + oneway void notifyListenersAsync (in DeviceEventListener listener, + in DeviceEvent event); + + Added DeviceEventListener and DeviceEvent structs (may deprecate + KeyStroke and KeystrokeListener in favor of this generic + event/listener framework for devices). + + * libspi/deviceeventcontroller.c: + + Changed some key listener code to take masks, etc., and paved the + way for integration of toolkit/non-preemptive key events. Changed + signatures of some internal methods. + + * at-bridge/bridge.c: + Fixed regression connecting to interface signals, apparently + caused by GTK+ changes. + + Added an internal bridge_state_listener to deal with + property-change:accessible-state signals. + + Changed the key_listeners GList to store structs (including masks, + etc.) instead of just CORBA_Objects (required for full + implementation of key listener API). + + Connected the bridge to all currently supported Atk signals. + Events now supported: + object:property-change + object:property-change:accessible-name + object:property-change:accessible-state + object:property-change:accessible-description + object:property-change:accessible-parent + object:property-change:accessible-value + object:property-change:accessible-role + object:property-change:accessible-table-caption + object:property-change:accessible-table-column-description + object:property-change:accessible-table-column-header + object:property-change:accessible-table-row-description + object:property-change:accessible-table-row-header + object:property-change:accessible-table-summary + object:children-changed + object:visible-data-changed + object:selection-changed + object:text-selection-changed + object:text-changed + object:text-caret-moved + object:row-inserted + object:row-reordered + object:row-deleted + object:column-inserted + object:column-reordered + object:column-deleted + object:model-changed + 2001-16-11 Bill Haneman + * libspi/hyperlink.c,h: + Fixed some broken stuff in hyperlink. + * libspi/relation.h: * libspi/relation.c: * cspi/spi_accessible.c: diff --git a/at-bridge/bridge.c b/at-bridge/bridge.c index 2d988ee..6c66892 100644 --- a/at-bridge/bridge.c +++ b/at-bridge/bridge.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "accessible.h" #include "application.h" @@ -54,6 +55,10 @@ static gboolean bridge_property_event_listener (GSignalInvocationHint *signal_hi guint n_param_values, const GValue *param_values, gpointer data); +static gboolean bridge_state_event_listener (GSignalInvocationHint *signal_hint, + guint n_param_values, + const GValue *param_values, + gpointer data); static gboolean bridge_signal_listener (GSignalInvocationHint *signal_hint, guint n_param_values, const GValue *param_values, @@ -125,19 +130,27 @@ bridge_register_app (gpointer gp) static void register_atk_event_listeners () { - /* Register for focus event notifications, and register app with central registry */ + GType t; + + /* + * kludge to make sure the Atk interface types are registered, otherwise + * the AtkText signal handlers below won't get registered + */ -/* kludge to make sure the Atk interface types are registered, otherwise - the AtkText signal handlers below won't get registered */ + AtkNoOpObject *o = atk_no_op_object_new (g_object_new (ATK_TYPE_OBJECT, NULL)); + + /* Register for focus event notifications, and register app with central registry */ - ATK_TYPE_TEXT; + g_type_class_ref (ATK_TYPE_TEXT); + g_type_class_ref (ATK_TYPE_SELECTION); + g_type_class_ref (ATK_TYPE_TABLE); atk_add_focus_tracker (bridge_focus_tracker); atk_add_global_event_listener (bridge_property_event_listener, "Gtk:AtkObject:property-change"); atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkObject:children-changed"); - atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkObject:model-changed"); - atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkObject:selection-changed"); atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkObject:visible-data-changed"); + atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkSelection:selection-changed"); + atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkText:text-selection-changed"); atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkText:text-changed"); atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkText:text-caret-moved"); atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkTable:row-inserted"); @@ -146,6 +159,7 @@ register_atk_event_listeners () atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkTable:column-inserted"); atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkTable:column-reordered"); atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkTable:column-deleted"); + atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkTable:model-changed"); atk_add_key_event_listener (bridge_key_listener, NULL); } @@ -219,10 +233,68 @@ bridge_property_event_listener (GSignalInvocationHint *signal_hint, return TRUE; } +static gboolean +bridge_state_event_listener (GSignalInvocationHint *signal_hint, + guint n_param_values, + const GValue *param_values, + gpointer data) +{ + Accessibility_Event *e = Accessibility_Event__alloc(); + Bonobo_Unknown source = NULL; + AtkObject *aobject; + AtkPropertyValues *values; + GObject *gobject; + GSignalQuery signal_query; + gchar *name; + char sbuf[APP_STATIC_BUFF_SZ]; + + g_signal_query (signal_hint->signal_id, &signal_query); + name = signal_query.signal_name; +#ifdef SPI_BRIDGE_DEBUG + fprintf (stderr, "Received (state) signal %s:%s\n", + g_type_name (signal_query.itype), name); +#endif + gobject = g_value_get_object (param_values + 0); + values = (AtkPropertyValues*) g_value_get_pointer (param_values + 1); + + /* notify the actual listeners */ + if (ATK_IS_IMPLEMENTOR (gobject)) + { + aobject = atk_implementor_ref_accessible (ATK_IMPLEMENTOR (gobject)); + source = CORBA_Object_duplicate (BONOBO_OBJREF (spi_accessible_new (aobject)), &ev); + g_object_unref (G_OBJECT(aobject)); + } + else if (ATK_IS_OBJECT (gobject)) + { + aobject = ATK_OBJECT (gobject); + source = CORBA_Object_duplicate (BONOBO_OBJREF (spi_accessible_new (aobject)), &ev); + } + else + { + g_error("received property-change event from non-AtkImplementor"); + } + + snprintf(sbuf, APP_STATIC_BUFF_SZ, "object:%s:%s", values->property_name, "?"); + e->type = CORBA_string_dup (sbuf); + e->source = source; + e->detail1 = (unsigned long) values->old_value.data[0].v_ulong; + e->detail2 = (unsigned long) values->new_value.data[0].v_ulong; + if (source) + Accessibility_Registry_notifyEvent (registry, e, &ev); + return TRUE; +} + static gint bridge_key_listener (AtkImplementor *atk_impl, AtkKeyEventStruct *event, gpointer data) { - g_print ("bridge key listener!\n"); + Accessibility_KeyStroke *key_event; + static Accessibility_DeviceEventController controller = CORBA_OBJECT_NIL; + if (controller == CORBA_OBJECT_NIL) + { + controller = Accessibility_Registry_getDeviceEventController (registry, &ev); + } + g_print ("bridge key listener fired!\n"); +/* Accessibility_DeviceEventController_notifyListenersSync (controller, key_event, &ev); */ } static gboolean @@ -243,7 +315,7 @@ bridge_signal_listener (GSignalInvocationHint *signal_hint, g_signal_query (signal_hint->signal_id, &signal_query); name = signal_query.signal_name; #ifdef SPI_BRIDGE_DEBUG - fprintf (stderr, "Received (property) signal %s:%s\n", + fprintf (stderr, "Received signal %s:%s\n", g_type_name (signal_query.itype), name); #endif gobject = g_value_get_object (param_values + 0); diff --git a/atk-bridge/bridge.c b/atk-bridge/bridge.c index 2d988ee..6c66892 100644 --- a/atk-bridge/bridge.c +++ b/atk-bridge/bridge.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include "accessible.h" #include "application.h" @@ -54,6 +55,10 @@ static gboolean bridge_property_event_listener (GSignalInvocationHint *signal_hi guint n_param_values, const GValue *param_values, gpointer data); +static gboolean bridge_state_event_listener (GSignalInvocationHint *signal_hint, + guint n_param_values, + const GValue *param_values, + gpointer data); static gboolean bridge_signal_listener (GSignalInvocationHint *signal_hint, guint n_param_values, const GValue *param_values, @@ -125,19 +130,27 @@ bridge_register_app (gpointer gp) static void register_atk_event_listeners () { - /* Register for focus event notifications, and register app with central registry */ + GType t; + + /* + * kludge to make sure the Atk interface types are registered, otherwise + * the AtkText signal handlers below won't get registered + */ -/* kludge to make sure the Atk interface types are registered, otherwise - the AtkText signal handlers below won't get registered */ + AtkNoOpObject *o = atk_no_op_object_new (g_object_new (ATK_TYPE_OBJECT, NULL)); + + /* Register for focus event notifications, and register app with central registry */ - ATK_TYPE_TEXT; + g_type_class_ref (ATK_TYPE_TEXT); + g_type_class_ref (ATK_TYPE_SELECTION); + g_type_class_ref (ATK_TYPE_TABLE); atk_add_focus_tracker (bridge_focus_tracker); atk_add_global_event_listener (bridge_property_event_listener, "Gtk:AtkObject:property-change"); atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkObject:children-changed"); - atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkObject:model-changed"); - atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkObject:selection-changed"); atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkObject:visible-data-changed"); + atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkSelection:selection-changed"); + atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkText:text-selection-changed"); atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkText:text-changed"); atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkText:text-caret-moved"); atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkTable:row-inserted"); @@ -146,6 +159,7 @@ register_atk_event_listeners () atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkTable:column-inserted"); atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkTable:column-reordered"); atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkTable:column-deleted"); + atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkTable:model-changed"); atk_add_key_event_listener (bridge_key_listener, NULL); } @@ -219,10 +233,68 @@ bridge_property_event_listener (GSignalInvocationHint *signal_hint, return TRUE; } +static gboolean +bridge_state_event_listener (GSignalInvocationHint *signal_hint, + guint n_param_values, + const GValue *param_values, + gpointer data) +{ + Accessibility_Event *e = Accessibility_Event__alloc(); + Bonobo_Unknown source = NULL; + AtkObject *aobject; + AtkPropertyValues *values; + GObject *gobject; + GSignalQuery signal_query; + gchar *name; + char sbuf[APP_STATIC_BUFF_SZ]; + + g_signal_query (signal_hint->signal_id, &signal_query); + name = signal_query.signal_name; +#ifdef SPI_BRIDGE_DEBUG + fprintf (stderr, "Received (state) signal %s:%s\n", + g_type_name (signal_query.itype), name); +#endif + gobject = g_value_get_object (param_values + 0); + values = (AtkPropertyValues*) g_value_get_pointer (param_values + 1); + + /* notify the actual listeners */ + if (ATK_IS_IMPLEMENTOR (gobject)) + { + aobject = atk_implementor_ref_accessible (ATK_IMPLEMENTOR (gobject)); + source = CORBA_Object_duplicate (BONOBO_OBJREF (spi_accessible_new (aobject)), &ev); + g_object_unref (G_OBJECT(aobject)); + } + else if (ATK_IS_OBJECT (gobject)) + { + aobject = ATK_OBJECT (gobject); + source = CORBA_Object_duplicate (BONOBO_OBJREF (spi_accessible_new (aobject)), &ev); + } + else + { + g_error("received property-change event from non-AtkImplementor"); + } + + snprintf(sbuf, APP_STATIC_BUFF_SZ, "object:%s:%s", values->property_name, "?"); + e->type = CORBA_string_dup (sbuf); + e->source = source; + e->detail1 = (unsigned long) values->old_value.data[0].v_ulong; + e->detail2 = (unsigned long) values->new_value.data[0].v_ulong; + if (source) + Accessibility_Registry_notifyEvent (registry, e, &ev); + return TRUE; +} + static gint bridge_key_listener (AtkImplementor *atk_impl, AtkKeyEventStruct *event, gpointer data) { - g_print ("bridge key listener!\n"); + Accessibility_KeyStroke *key_event; + static Accessibility_DeviceEventController controller = CORBA_OBJECT_NIL; + if (controller == CORBA_OBJECT_NIL) + { + controller = Accessibility_Registry_getDeviceEventController (registry, &ev); + } + g_print ("bridge key listener fired!\n"); +/* Accessibility_DeviceEventController_notifyListenersSync (controller, key_event, &ev); */ } static gboolean @@ -243,7 +315,7 @@ bridge_signal_listener (GSignalInvocationHint *signal_hint, g_signal_query (signal_hint->signal_id, &signal_query); name = signal_query.signal_name; #ifdef SPI_BRIDGE_DEBUG - fprintf (stderr, "Received (property) signal %s:%s\n", + fprintf (stderr, "Received signal %s:%s\n", g_type_name (signal_query.itype), name); #endif gobject = g_value_get_object (param_values + 0); diff --git a/cspi/spi-listener.h b/cspi/spi-listener.h index 678ad55..ec8b265 100644 --- a/cspi/spi-listener.h +++ b/cspi/spi-listener.h @@ -9,9 +9,6 @@ extern "C" { #include "accessibleeventlistener.h" #include "keystrokelistener.h" -#define SPI_KEYSET_ALL_KEYS ((void *)NULL) - - /* * * Structure used to encapsulate event information diff --git a/cspi/spi.h b/cspi/spi.h index 1a7dc53..b29719e 100644 --- a/cspi/spi.h +++ b/cspi/spi.h @@ -111,7 +111,7 @@ typedef struct _AccessibleKeySet * @SPI_KEYSET_ALL_KEYS: A special value for an AccessibleKeySet type, which tacitly * includes all keycodes and keyvals for the specified modifier set. **/ -#define SPI_KEYSET_ALL_KEYS ((void *)NULL) +#define SPI_KEYSET_ALL_KEYS NULL typedef unsigned long AccessibleKeyMaskType; diff --git a/cspi/spi_accessible.c b/cspi/spi_accessible.c index bdeef1f..31fb819 100644 --- a/cspi/spi_accessible.c +++ b/cspi/spi_accessible.c @@ -809,3 +809,157 @@ AccessibleRelation_getTarget (AccessibleRelation *obj, int i) { return NULL; } + +/** + * AccessibleStateSet_ref: + * @obj: a pointer to the #AccessibleStateSet object on which to operate. + * + * Increment the reference count for an #AccessibleStateSet object. + * + * Returns: (no return code implemented yet). + * + **/ +int +AccessibleStateSet_ref (AccessibleStateSet *obj) +{ +/* Accessibility_StateSet_ref (*obj, &ev); */ + spi_check_ev (&ev, "ref"); + return 0; +} + +/** + * AccessibleStateSet_unref: + * @obj: a pointer to the #AccessibleStateSet object on which to operate. + * + * Decrement the reference count for an #AccessibleStateSet object. + * + * Returns: (no return code implemented yet). + * + **/ +int +AccessibleStateSet_unref (AccessibleStateSet *obj) +{ +/* Accessibility_StateSet_unref (*obj, &ev); */ + spi_check_ev (&ev, "unref"); + return 0; +} + + +/** + * AccessibleStateSet_contains: + * @obj: a pointer to the #AccessibleStateSet object on which to operate. + * @state: an #AccessibleState for which the specified #AccessibleStateSet + * will be queried. + * + * Determine whether a given #AccessibleStateSet includes a given state; that is, + * whether @state is true for the stateset in question. + * + * Returns: #TRUE if @state is true/included in the given #AccessibleStateSet, + * otherwise #FALSE. + * + **/ +boolean +AccessibleStateSet_contains (AccessibleStateSet *obj, + AccessibleState state) +{ + CORBA_boolean retval = Accessibility_StateSet_contains (*obj, state, &ev); + spi_check_ev (&ev, "contains"); + return (boolean) retval; +} + +/** + * AccessibleStateSet_add: + * @obj: a pointer to the #AccessibleStateSet object on which to operate. + * @state: an #AccessibleState to be added to the specified #AccessibleStateSet + * + * Add a particular #AccessibleState to an #AccessibleStateSet (i.e. set the + * given state to #TRUE in the stateset. + * + **/ +void +AccessibleStateSet_add (AccessibleStateSet *obj, + AccessibleState state) +{ + Accessibility_StateSet_add (*obj, state, &ev); + spi_check_ev (&ev, "contains"); +} + + +/** + * AccessibleStateSet_remove: + * @obj: a pointer to the #AccessibleStateSet object on which to operate. + * @state: an #AccessibleState to be removed from the specified #AccessibleStateSet + * + * Remove a particular #AccessibleState to an #AccessibleStateSet (i.e. set the + * given state to #FALSE in the stateset.) + * + **/ +void +AccessibleStateSet_remove (AccessibleStateSet *obj, + AccessibleState state) +{ + Accessibility_StateSet_remove (*obj, state, &ev); + spi_check_ev (&ev, "contains"); +} + +/** + * AccessibleStateSet_equals: + * @obj: a pointer to the first #AccessibleStateSet object on which to operate. + * @obj2: a pointer to the second #AccessibleStateSet object on which to operate. + * + * Determine whether two instances of #AccessibleStateSet are equivalent (i.e. + * consist of the same #AccessibleStates). Useful for checking multiple + * state variables at once; construct the target state then compare against it. + * + * @see AccessibleStateSet_compare(). + * + * Returns: #TRUE if the two #AccessibleStateSets are equivalent, + * otherwise #FALSE. + * + **/ +boolean +AccessibleStateSet_equals (AccessibleStateSet *obj, + AccessibleStateSet *obj2) +{ + return Accessibility_StateSet_equals (*obj, *obj2, &ev); +} + +/** + * AccessibleStateSet_compare: + * @obj: a pointer to the first #AccessibleStateSet object on which to operate. + * @obj2: a pointer to the second #AccessibleStateSet object on which to operate. + * + * Determine the differences between two instances of #AccessibleStateSet. + *. + * @see AccessibleStateSet_equals(). + * + * Returns: an #AccessibleStateSet object containing all states contained on one of + * the two sets but not the other. + * + **/ +void +AccessibleStateSet_compare (AccessibleStateSet *obj, + AccessibleStateSet *obj2, + AccessibleStateSet **differenceSet); + + +/** + * AccessibleStateSet_isEmpty: + * @obj: a pointer to the #AccessibleStateSet object on which to operate. + * + * Determine whether a given #AccessibleStateSet is the empty set. + * + * Returns: #TRUE if the given #AccessibleStateSet contains no (true) states, + * otherwise #FALSE. + * + **/ +boolean +AccessibleStateSet_isEmpty (AccessibleStateSet *obj) +{ + return TRUE; + /* return Accessibility_StateSet_isEmpty (*obj, &ev);*/ +} + + + + diff --git a/cspi/spi_registry.c b/cspi/spi_registry.c index 72f9314..40f81b7 100644 --- a/cspi/spi_registry.c +++ b/cspi/spi_registry.c @@ -17,10 +17,44 @@ static Display *display = NULL; * notification is requested. Format is * EventClass:major_type:minor_type:detail * where all subfields other than EventClass are optional. - * EventClasses include "Focus", "Window", "Mouse", + * EventClasses include "object", "window", "mouse", * and toolkit events (e.g. "Gtk", "AWT"). * Examples: "focus:", "Gtk:GtkWidget:button_press_event". * + * Legal object event types: + * + * (property change events) + * + * object:property-change + * object:property-change:accessible-name + * object:property-change:accessible-state + * object:property-change:accessible-description + * object:property-change:accessible-parent + * object:property-change:accessible-value + * object:property-change:accessible-role + * object:property-change:accessible-table-caption + * object:property-change:accessible-table-column-description + * object:property-change:accessible-table-column-header + * object:property-change:accessible-table-row-description + * object:property-change:accessible-table-row-header + * object:property-change:accessible-table-summary + * + * (other object events) + * + * object:children-changed + * object:visible-data-changed + * object:selection-changed + * object:text-selection-changed + * object:text-changed + * object:text-caret-moved + * object:row-inserted + * object:row-reordered + * object:row-deleted + * object:column-inserted + * object:column-reordered + * object:column-deleted + * object:model-changed + * * NOTE: this string may be UTF-8, but should not contain byte value 56 * (ascii ':'), except as a delimiter, since non-UTF-8 string * delimiting functions are used internally. diff --git a/docs/at-spi-sections.txt b/docs/at-spi-sections.txt index 2eeaa9b..a6bdd0e 100644 --- a/docs/at-spi-sections.txt +++ b/docs/at-spi-sections.txt @@ -31,7 +31,6 @@ AccessibleKeyEventMask AccessibleKeyMaskType AccessibleKeyEventType AccessibleKeyListenerSyncType -SPI_KEYSET_ALL_KEYS createAccessibleKeystrokeListener registerGlobalEventListener deregisterGlobalEventListener diff --git a/idl/Accessibility_Registry.idl b/idl/Accessibility_Registry.idl index 5908106..2e56cf3 100644 --- a/idl/Accessibility_Registry.idl +++ b/idl/Accessibility_Registry.idl @@ -157,6 +157,11 @@ module Accessibility { KEY_RELEASED }; + enum EventType { + KEY_PRESSED_EVENT, + KEY_RELEASED_EVENT + }; + enum KeySynthType { KEY_PRESS, KEY_RELEASE, @@ -183,10 +188,19 @@ module Accessibility { struct KeyStroke { long keyID; short keycode; + unsigned long timestamp; KeyEventType type; unsigned short modifiers; }; + struct DeviceEvent { + long eventID; + short hw_code; + unsigned long timestamp; + EventType type; + unsigned short modifiers; + }; + typedef sequence< long > KeySet; typedef sequence< KeyEventType > KeyEventTypeSeq; @@ -194,6 +208,10 @@ module Accessibility { boolean keyEvent (in KeyStroke key); }; + interface DeviceEventListener : Bonobo::Unknown { + boolean notifyEvent (in DeviceEvent event); + }; + interface DeviceEventController : Bonobo::Unknown { /** @@ -239,6 +257,12 @@ module Accessibility { in KeyEventTypeSeq type, in boolean is_synchronous); + boolean notifyListenersSync (in DeviceEventListener listener, + in DeviceEvent event); + + oneway void notifyListenersAsync (in DeviceEventListener listener, + in DeviceEvent event); + /** * generateKeyEvent: * @keycode: a long integer indicating the keycode of diff --git a/idl/Registry.idl b/idl/Registry.idl index 5908106..2e56cf3 100644 --- a/idl/Registry.idl +++ b/idl/Registry.idl @@ -157,6 +157,11 @@ module Accessibility { KEY_RELEASED }; + enum EventType { + KEY_PRESSED_EVENT, + KEY_RELEASED_EVENT + }; + enum KeySynthType { KEY_PRESS, KEY_RELEASE, @@ -183,10 +188,19 @@ module Accessibility { struct KeyStroke { long keyID; short keycode; + unsigned long timestamp; KeyEventType type; unsigned short modifiers; }; + struct DeviceEvent { + long eventID; + short hw_code; + unsigned long timestamp; + EventType type; + unsigned short modifiers; + }; + typedef sequence< long > KeySet; typedef sequence< KeyEventType > KeyEventTypeSeq; @@ -194,6 +208,10 @@ module Accessibility { boolean keyEvent (in KeyStroke key); }; + interface DeviceEventListener : Bonobo::Unknown { + boolean notifyEvent (in DeviceEvent event); + }; + interface DeviceEventController : Bonobo::Unknown { /** @@ -239,6 +257,12 @@ module Accessibility { in KeyEventTypeSeq type, in boolean is_synchronous); + boolean notifyListenersSync (in DeviceEventListener listener, + in DeviceEvent event); + + oneway void notifyListenersAsync (in DeviceEventListener listener, + in DeviceEvent event); + /** * generateKeyEvent: * @keycode: a long integer indicating the keycode of diff --git a/libspi/deviceeventcontroller.c b/libspi/deviceeventcontroller.c index 04f0371..9d2e6e1 100644 --- a/libspi/deviceeventcontroller.c +++ b/libspi/deviceeventcontroller.c @@ -60,26 +60,48 @@ static Display *display; static Window root_window; typedef enum { - DEVICE_TYPE_KBD, - DEVICE_TYPE_MOUSE, - DEVICE_TYPE_LAST_DEFINED -} DeviceTypeCategory; + SPI_DEVICE_TYPE_KBD, + SPI_DEVICE_TYPE_MOUSE, + SPI_DEVICE_TYPE_LAST_DEFINED +} SpiDeviceTypeCategory; + +struct _DEControllerListener { + CORBA_Object object; + SpiDeviceTypeCategory type; +}; + +typedef struct _DEControllerListener DEControllerListener; + +struct _DEControllerKeyListener { + DEControllerListener listener; + Accessibility_KeySet *keys; + Accessibility_ControllerEventMask *mask; + Accessibility_KeyEventTypeSeq *typeseq; + gboolean is_system_global; +}; + +typedef struct _DEControllerKeyListener DEControllerKeyListener; static gboolean _controller_register_with_devices (SpiDeviceEventController *controller); static gboolean _controller_grab_keyboard (SpiDeviceEventController *controller); -static void _controller_register_device_listener (SpiDeviceEventController *controller, - const CORBA_Object l, - DeviceTypeCategory type, - const Accessibility_KeySet *keys, - const Accessibility_ControllerEventMask *mask, - CORBA_Environment *ev); +static void controller_register_device_listener (SpiDeviceEventController *controller, + DEControllerListener *l, + CORBA_Environment *ev); /* * Private methods */ static gint +_compare_listeners (gconstpointer p1, gconstpointer p2) +{ + DEControllerListener *l1 = (DEControllerListener *) p1; + DEControllerListener *l2 = (DEControllerListener *) p2; + return _compare_corba_objects (l1->object, l2->object); +} + +static gint _compare_corba_objects (gconstpointer p1, gconstpointer p2) { CORBA_Environment ev; @@ -106,44 +128,60 @@ _eventmask_compare_value (gconstpointer p1, gconstpointer p2) return (gint) d; } +static DEControllerKeyListener * +dec_key_listener_new (CORBA_Object l, + const Accessibility_KeySet *keys, + const Accessibility_ControllerEventMask *mask, + const Accessibility_KeyEventTypeSeq *typeseq, + const CORBA_boolean is_system_global, + CORBA_Environment *ev) +{ + DEControllerKeyListener *key_listener = g_new0 (DEControllerKeyListener, 1); + key_listener->listener.object = CORBA_Object_duplicate (l, ev); + key_listener->listener.type = SPI_DEVICE_TYPE_KBD; + key_listener->keys = keys; + key_listener->mask = mask; + key_listener->is_system_global = is_system_global; + + return key_listener; +} + static void -_controller_register_device_listener (SpiDeviceEventController *controller, - const CORBA_Object l, - DeviceTypeCategory type, - const Accessibility_KeySet *keys, - const Accessibility_ControllerEventMask *mask, - CORBA_Environment *ev) +controller_register_device_listener (SpiDeviceEventController *controller, + DEControllerListener *listener, + CORBA_Environment *ev) { Accessibility_ControllerEventMask *mask_ptr = NULL; + DEControllerKeyListener *key_listener; - switch (type) { - case DEVICE_TYPE_KBD: - controller->key_listeners = g_list_append (controller->key_listeners, - CORBA_Object_duplicate (l, ev)); + switch (listener->type) { + case SPI_DEVICE_TYPE_KBD: + key_listener = (DEControllerKeyListener *) listener; + controller->key_listeners = g_list_append (controller->key_listeners, key_listener); mask_ptr = (Accessibility_ControllerEventMask *) - g_list_find_custom (controller->keymask_list, (gpointer) mask, + g_list_find_custom (controller->keymask_list, (gpointer) key_listener->mask, _eventmask_compare_value); if (mask_ptr) ++(mask_ptr->refcount); else { - if (mask->refcount != (CORBA_unsigned_short) 1) + if (key_listener->mask->refcount != (CORBA_unsigned_short) 1) fprintf (stderr, "mask initial refcount is not 1!\n"); - if (mask->value > (CORBA_unsigned_long) 2048) + if (key_listener->mask->value > (CORBA_unsigned_long) 2048) fprintf (stderr, "mask value looks invalid (%lu)\n", - (unsigned long) mask->value); + (unsigned long) key_listener->mask->value); else fprintf (stderr, "appending mask with val=%lu\n", - (unsigned long) mask->value); + (unsigned long) key_listener->mask->value); mask_ptr = Accessibility_ControllerEventMask__alloc(); - mask_ptr->value = mask->value; + mask_ptr->value = key_listener->mask->value; mask_ptr->refcount = (CORBA_unsigned_short) 1; controller->keymask_list = g_list_append (controller->keymask_list, (gpointer) mask_ptr); } break; - case DEVICE_TYPE_MOUSE: + case SPI_DEVICE_TYPE_MOUSE: /* controller->mouse_listeners = g_list_append (controller->mouse_listeners, CORBA_Object_duplicate (l, ev));*/ @@ -153,21 +191,22 @@ _controller_register_device_listener (SpiDeviceEventController *controller, } static void -_controller_deregister_device_listener (SpiDeviceEventController *controller, - const CORBA_Object l, - const Accessibility_ControllerEventMask *mask, - DeviceTypeCategory type, - CORBA_Environment *ev) +controller_deregister_device_listener (SpiDeviceEventController *controller, + DEControllerListener *listener, + CORBA_Environment *ev) { Accessibility_ControllerEventMask *mask_ptr; + DEControllerKeyListener *key_listener; GList *list_ptr; - switch (type) { - case DEVICE_TYPE_KBD: - list_ptr = g_list_find_custom (controller->key_listeners, l, _compare_corba_objects); + switch (listener->type) { + case SPI_DEVICE_TYPE_KBD: + key_listener = (DEControllerKeyListener *) listener; + list_ptr = g_list_find_custom (controller->key_listeners, listener, _compare_listeners); + /* TODO: need a different custom compare func */ if (list_ptr) controller->key_listeners = g_list_remove (controller->key_listeners, list_ptr); list_ptr = (GList *) - g_list_find_custom (controller->keymask_list, (gpointer) mask, + g_list_find_custom (controller->keymask_list, (gpointer) key_listener->mask, _eventmask_compare_value); if (list_ptr) { @@ -182,7 +221,7 @@ _controller_deregister_device_listener (SpiDeviceEventController *controller, } } break; - case DEVICE_TYPE_MOUSE: + case SPI_DEVICE_TYPE_MOUSE: /* controller->mouse_listeners = g_list_append (controller->mouse_listeners, CORBA_Object_duplicate (l, ev));*/ @@ -214,6 +253,26 @@ _controller_register_with_devices (SpiDeviceEventController *controller) return retval; } + +static gboolean +notify_keylisteners (GList *key_listeners, Accessibility_KeyStroke *key_event, CORBA_Environment *ev) +{ + int i, n_listeners = g_list_length (key_listeners); + gboolean is_consumed = FALSE; + for (i=0; ikey_listeners); Accessibility_KeyStroke key_event; static CORBA_Environment ev; @@ -268,16 +326,8 @@ _check_key_event (SpiDeviceEventController *controller) #endif } /* relay to listeners, and decide whether to consume it or not */ - for (i=0; ikey_listeners, i); - if (!CORBA_Object_is_nil(ls, &ev)) - { - is_consumed = Accessibility_KeystrokeListener_keyEvent (ls, &key_event, &ev); - } - } + is_consumed = notify_keylisteners (controller->key_listeners, &key_event, &ev); + if (is_consumed) { XAllowEvents (display, SyncKeyboard, CurrentTime); @@ -363,15 +413,13 @@ impl_register_keystroke_listener (PortableServer_Servant servant, { SpiDeviceEventController *controller = SPI_DEVICE_EVENT_CONTROLLER ( bonobo_object_from_servant (servant)); + DEControllerKeyListener *dec_listener; #ifdef SPI_DEBUG fprintf (stderr, "registering keystroke listener %p with maskVal %lu\n", (void *) l, (unsigned long) mask->value); #endif - /* TODO: change this to an enum, indicating if event is caught at OS level */ - if (is_system_global) - _controller_register_device_listener(controller, l, DEVICE_TYPE_KBD, keys, mask, ev); - else - ; /* register with toolkit instead */ + dec_listener = dec_key_listener_new (l, keys, mask, type, is_system_global, ev); + controller_register_device_listener (controller, (DEControllerListener *) dec_listener, ev); } /* @@ -384,16 +432,24 @@ impl_deregister_keystroke_listener (PortableServer_Servant servant, const Accessibility_KeySet *keys, const Accessibility_ControllerEventMask *mask, const Accessibility_KeyEventTypeSeq *type, - const CORBA_boolean is_synchronous, + const CORBA_boolean is_system_global, CORBA_Environment *ev) { SpiDeviceEventController *controller = SPI_DEVICE_EVENT_CONTROLLER ( bonobo_object_from_servant (servant)); + DEControllerKeyListener *key_listener = dec_key_listener_new (l, + keys, + mask, + type, + is_system_global, + ev); #ifdef SPI_DEBUG fprintf (stderr, "deregistering keystroke listener %p with maskVal %lu\n", (void *) l, (unsigned long) mask->value); #endif - _controller_deregister_device_listener(controller, l, mask, DEVICE_TYPE_KBD, ev); + controller_deregister_device_listener(controller, + (DEControllerListener *) key_listener, + ev); } /* @@ -411,7 +467,7 @@ impl_register_mouse_listener (PortableServer_Servant servant, #ifdef SPI_DEBUG fprintf (stderr, "registering mouse listener %p\n", l); #endif - _controller_register_device_listener(controller, DEVICE_TYPE_MOUSE, l, keys, mask, ev); + controller_register_device_listener(controller, DEVICE_TYPE_MOUSE, l, keys, mask, ev); } */ diff --git a/libspi/registry.c b/libspi/registry.c index a607020..05fc512 100644 --- a/libspi/registry.c +++ b/libspi/registry.c @@ -64,6 +64,8 @@ typedef enum { ETYPE_PROPERTY, ETYPE_WINDOW, ETYPE_TOOLKIT, + ETYPE_KEYBOARD, + ETYPE_LAST_DEFINED } EventTypeCategory; @@ -518,6 +520,7 @@ impl_registry_notify_event (PortableServer_Servant servant, case (ETYPE_TOOLKIT) : _registry_notify_listeners (registry->toolkit_listeners, e, ev); break; + case (ETYPE_KEYBOARD) : default: break; } diff --git a/registryd/deviceeventcontroller.c b/registryd/deviceeventcontroller.c index 04f0371..9d2e6e1 100644 --- a/registryd/deviceeventcontroller.c +++ b/registryd/deviceeventcontroller.c @@ -60,26 +60,48 @@ static Display *display; static Window root_window; typedef enum { - DEVICE_TYPE_KBD, - DEVICE_TYPE_MOUSE, - DEVICE_TYPE_LAST_DEFINED -} DeviceTypeCategory; + SPI_DEVICE_TYPE_KBD, + SPI_DEVICE_TYPE_MOUSE, + SPI_DEVICE_TYPE_LAST_DEFINED +} SpiDeviceTypeCategory; + +struct _DEControllerListener { + CORBA_Object object; + SpiDeviceTypeCategory type; +}; + +typedef struct _DEControllerListener DEControllerListener; + +struct _DEControllerKeyListener { + DEControllerListener listener; + Accessibility_KeySet *keys; + Accessibility_ControllerEventMask *mask; + Accessibility_KeyEventTypeSeq *typeseq; + gboolean is_system_global; +}; + +typedef struct _DEControllerKeyListener DEControllerKeyListener; static gboolean _controller_register_with_devices (SpiDeviceEventController *controller); static gboolean _controller_grab_keyboard (SpiDeviceEventController *controller); -static void _controller_register_device_listener (SpiDeviceEventController *controller, - const CORBA_Object l, - DeviceTypeCategory type, - const Accessibility_KeySet *keys, - const Accessibility_ControllerEventMask *mask, - CORBA_Environment *ev); +static void controller_register_device_listener (SpiDeviceEventController *controller, + DEControllerListener *l, + CORBA_Environment *ev); /* * Private methods */ static gint +_compare_listeners (gconstpointer p1, gconstpointer p2) +{ + DEControllerListener *l1 = (DEControllerListener *) p1; + DEControllerListener *l2 = (DEControllerListener *) p2; + return _compare_corba_objects (l1->object, l2->object); +} + +static gint _compare_corba_objects (gconstpointer p1, gconstpointer p2) { CORBA_Environment ev; @@ -106,44 +128,60 @@ _eventmask_compare_value (gconstpointer p1, gconstpointer p2) return (gint) d; } +static DEControllerKeyListener * +dec_key_listener_new (CORBA_Object l, + const Accessibility_KeySet *keys, + const Accessibility_ControllerEventMask *mask, + const Accessibility_KeyEventTypeSeq *typeseq, + const CORBA_boolean is_system_global, + CORBA_Environment *ev) +{ + DEControllerKeyListener *key_listener = g_new0 (DEControllerKeyListener, 1); + key_listener->listener.object = CORBA_Object_duplicate (l, ev); + key_listener->listener.type = SPI_DEVICE_TYPE_KBD; + key_listener->keys = keys; + key_listener->mask = mask; + key_listener->is_system_global = is_system_global; + + return key_listener; +} + static void -_controller_register_device_listener (SpiDeviceEventController *controller, - const CORBA_Object l, - DeviceTypeCategory type, - const Accessibility_KeySet *keys, - const Accessibility_ControllerEventMask *mask, - CORBA_Environment *ev) +controller_register_device_listener (SpiDeviceEventController *controller, + DEControllerListener *listener, + CORBA_Environment *ev) { Accessibility_ControllerEventMask *mask_ptr = NULL; + DEControllerKeyListener *key_listener; - switch (type) { - case DEVICE_TYPE_KBD: - controller->key_listeners = g_list_append (controller->key_listeners, - CORBA_Object_duplicate (l, ev)); + switch (listener->type) { + case SPI_DEVICE_TYPE_KBD: + key_listener = (DEControllerKeyListener *) listener; + controller->key_listeners = g_list_append (controller->key_listeners, key_listener); mask_ptr = (Accessibility_ControllerEventMask *) - g_list_find_custom (controller->keymask_list, (gpointer) mask, + g_list_find_custom (controller->keymask_list, (gpointer) key_listener->mask, _eventmask_compare_value); if (mask_ptr) ++(mask_ptr->refcount); else { - if (mask->refcount != (CORBA_unsigned_short) 1) + if (key_listener->mask->refcount != (CORBA_unsigned_short) 1) fprintf (stderr, "mask initial refcount is not 1!\n"); - if (mask->value > (CORBA_unsigned_long) 2048) + if (key_listener->mask->value > (CORBA_unsigned_long) 2048) fprintf (stderr, "mask value looks invalid (%lu)\n", - (unsigned long) mask->value); + (unsigned long) key_listener->mask->value); else fprintf (stderr, "appending mask with val=%lu\n", - (unsigned long) mask->value); + (unsigned long) key_listener->mask->value); mask_ptr = Accessibility_ControllerEventMask__alloc(); - mask_ptr->value = mask->value; + mask_ptr->value = key_listener->mask->value; mask_ptr->refcount = (CORBA_unsigned_short) 1; controller->keymask_list = g_list_append (controller->keymask_list, (gpointer) mask_ptr); } break; - case DEVICE_TYPE_MOUSE: + case SPI_DEVICE_TYPE_MOUSE: /* controller->mouse_listeners = g_list_append (controller->mouse_listeners, CORBA_Object_duplicate (l, ev));*/ @@ -153,21 +191,22 @@ _controller_register_device_listener (SpiDeviceEventController *controller, } static void -_controller_deregister_device_listener (SpiDeviceEventController *controller, - const CORBA_Object l, - const Accessibility_ControllerEventMask *mask, - DeviceTypeCategory type, - CORBA_Environment *ev) +controller_deregister_device_listener (SpiDeviceEventController *controller, + DEControllerListener *listener, + CORBA_Environment *ev) { Accessibility_ControllerEventMask *mask_ptr; + DEControllerKeyListener *key_listener; GList *list_ptr; - switch (type) { - case DEVICE_TYPE_KBD: - list_ptr = g_list_find_custom (controller->key_listeners, l, _compare_corba_objects); + switch (listener->type) { + case SPI_DEVICE_TYPE_KBD: + key_listener = (DEControllerKeyListener *) listener; + list_ptr = g_list_find_custom (controller->key_listeners, listener, _compare_listeners); + /* TODO: need a different custom compare func */ if (list_ptr) controller->key_listeners = g_list_remove (controller->key_listeners, list_ptr); list_ptr = (GList *) - g_list_find_custom (controller->keymask_list, (gpointer) mask, + g_list_find_custom (controller->keymask_list, (gpointer) key_listener->mask, _eventmask_compare_value); if (list_ptr) { @@ -182,7 +221,7 @@ _controller_deregister_device_listener (SpiDeviceEventController *controller, } } break; - case DEVICE_TYPE_MOUSE: + case SPI_DEVICE_TYPE_MOUSE: /* controller->mouse_listeners = g_list_append (controller->mouse_listeners, CORBA_Object_duplicate (l, ev));*/ @@ -214,6 +253,26 @@ _controller_register_with_devices (SpiDeviceEventController *controller) return retval; } + +static gboolean +notify_keylisteners (GList *key_listeners, Accessibility_KeyStroke *key_event, CORBA_Environment *ev) +{ + int i, n_listeners = g_list_length (key_listeners); + gboolean is_consumed = FALSE; + for (i=0; ikey_listeners); Accessibility_KeyStroke key_event; static CORBA_Environment ev; @@ -268,16 +326,8 @@ _check_key_event (SpiDeviceEventController *controller) #endif } /* relay to listeners, and decide whether to consume it or not */ - for (i=0; ikey_listeners, i); - if (!CORBA_Object_is_nil(ls, &ev)) - { - is_consumed = Accessibility_KeystrokeListener_keyEvent (ls, &key_event, &ev); - } - } + is_consumed = notify_keylisteners (controller->key_listeners, &key_event, &ev); + if (is_consumed) { XAllowEvents (display, SyncKeyboard, CurrentTime); @@ -363,15 +413,13 @@ impl_register_keystroke_listener (PortableServer_Servant servant, { SpiDeviceEventController *controller = SPI_DEVICE_EVENT_CONTROLLER ( bonobo_object_from_servant (servant)); + DEControllerKeyListener *dec_listener; #ifdef SPI_DEBUG fprintf (stderr, "registering keystroke listener %p with maskVal %lu\n", (void *) l, (unsigned long) mask->value); #endif - /* TODO: change this to an enum, indicating if event is caught at OS level */ - if (is_system_global) - _controller_register_device_listener(controller, l, DEVICE_TYPE_KBD, keys, mask, ev); - else - ; /* register with toolkit instead */ + dec_listener = dec_key_listener_new (l, keys, mask, type, is_system_global, ev); + controller_register_device_listener (controller, (DEControllerListener *) dec_listener, ev); } /* @@ -384,16 +432,24 @@ impl_deregister_keystroke_listener (PortableServer_Servant servant, const Accessibility_KeySet *keys, const Accessibility_ControllerEventMask *mask, const Accessibility_KeyEventTypeSeq *type, - const CORBA_boolean is_synchronous, + const CORBA_boolean is_system_global, CORBA_Environment *ev) { SpiDeviceEventController *controller = SPI_DEVICE_EVENT_CONTROLLER ( bonobo_object_from_servant (servant)); + DEControllerKeyListener *key_listener = dec_key_listener_new (l, + keys, + mask, + type, + is_system_global, + ev); #ifdef SPI_DEBUG fprintf (stderr, "deregistering keystroke listener %p with maskVal %lu\n", (void *) l, (unsigned long) mask->value); #endif - _controller_deregister_device_listener(controller, l, mask, DEVICE_TYPE_KBD, ev); + controller_deregister_device_listener(controller, + (DEControllerListener *) key_listener, + ev); } /* @@ -411,7 +467,7 @@ impl_register_mouse_listener (PortableServer_Servant servant, #ifdef SPI_DEBUG fprintf (stderr, "registering mouse listener %p\n", l); #endif - _controller_register_device_listener(controller, DEVICE_TYPE_MOUSE, l, keys, mask, ev); + controller_register_device_listener(controller, DEVICE_TYPE_MOUSE, l, keys, mask, ev); } */ diff --git a/registryd/registry.c b/registryd/registry.c index a607020..05fc512 100644 --- a/registryd/registry.c +++ b/registryd/registry.c @@ -64,6 +64,8 @@ typedef enum { ETYPE_PROPERTY, ETYPE_WINDOW, ETYPE_TOOLKIT, + ETYPE_KEYBOARD, + ETYPE_LAST_DEFINED } EventTypeCategory; @@ -518,6 +520,7 @@ impl_registry_notify_event (PortableServer_Servant servant, case (ETYPE_TOOLKIT) : _registry_notify_listeners (registry->toolkit_listeners, e, ev); break; + case (ETYPE_KEYBOARD) : default: break; }