From: billh Date: Tue, 19 Nov 2002 20:04:23 +0000 (+0000) Subject: Fixes for 98836, 98842, added slots to IDL for ABI freeze. X-Git-Tag: AT_SPI2_ATK_2_12_0~1310 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git;a=commitdiff_plain;h=3af8a4e874f524c212a01e4469db1c8043f1427f Fixes for 98836, 98842, added slots to IDL for ABI freeze. API/ABI freeze candidate for GNOME 2.2 (2.1.3 release). git-svn-id: http://svn.gnome.org/svn/at-spi/trunk@362 e2bd861d-eb25-0410-b326-f6ed22b6b98c --- diff --git a/ChangeLog b/ChangeLog index db1f0b0..ea0d226 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,158 @@ +2002-11-19 Bill Haneman + + FIXES for 98836, 98842, other bugs. + + * configure.in: + Revved to 1.1.4, interface-age=4, binary-age=4. + + * registryd/deviceeventcontroller.c: + (statics): + Fixed crasher bug in last_mouse_pos initialization. + + * registryd/registry.c: + (desktop_add_application, desktop_remove_application): + Added (and then commented out) some support for + object context marshalling. [TODO] + + * atk-bridge/bridge.c: + (spi_atk_bridge_event_context_create): + Commented out object context creation until it can + be properly tested and debugged. + + * registryd/registry.c: + (impl_registry_notify_event): + Fixed crasher bug, we were calling + spi_re_entrant_list_foreach () with an empty list. + +2002-11-18 Bill Haneman + + * idl/Accessibility_Action.idl: + * idl/Accessibility_Component.idl: + * idl/Accessibility_Desktop.idl: + * idl/Accessibility_Event.idl: + * idl/Accessibility_Hyperlink.idl: + * idl/Accessibility_Image.idl: + * idl/Accessibility_Relation.idl: + * idl/Accessibility_Selection.idl: + * idl/Accessibility_State.idl: + * idl/Accessibility_Value.idl: + Updated unimplemented slot count to minimum of + four for all interfaces, for ABI freeze. + + * idl/Accessibility_EditableText.idl: + * idl/Accessibility_Text.idl: + Updated unimplemented slot count to six + for ABI freeze. + + * idl/Accessibility_Registry.idl: + Updated unimplemented slot count to six + (also for DeviceEventController), + for ABI freeze. + + * idl/Accessibility_Table.idl: + Updated unimplemented slot count to eight, + for ABI freeze. + + * idl/Accessibility_Event.idl: + Added CORBA_any "any_data" member to Event struct. + + * idl/Accessibility_Event.idl: + Added CORBA_any "any_data" member to Event struct. + + * atk-bridge/bridge.c: + (statics): + atk_signal_text_changed, atk_signal_child_changed, + signal ids queried from gtype system. + (AtkBridgeEventContextType): New enum. + (AtkBridgeEventContextData): New struct. + (AtkBridgeEventContext): New struct. + (atk_bridge_init_event_type_consts): + New method, initializes type contants for comparison + prior to emit_eventv. + (atk_bridge_event_context_init): New method, + initializes a CORBA_any from an AtkBridgeEventContext. + (atk_bridge_focus_tracker): Call spi_init_any_nil to + initialize the event.any_data struct. + (spi_atk_bridge_event_context_create): New method, + creates an AtkBridgeEventContext from signal/event info. + (spi_atk_bridge_event_context_free): New method. + (spi_atk_emit_eventv): Changed to take an + AtkBridgeEventContext parameter. We now initialize + the event.any_data member prior to notifying the + Registry, via the AtkBridgeEventContext. + (spi_atk_bridge_property_event_listener): + (spi_atk_bridge_state_event_listener): + Match emit_eventv signature. + (spi_atk_bridge_object_event_listener): + Match emit_eventv signature, and create an + event context from the event details. + Free the event context afterwards. + (spi_atk_bridge_window_event_listener): + Create an event context, pass it to the + emit_eventv call. + + * cspi/spi_event.c: + (AccessibleEvent_getContextString): + (AccessibleEvent_getContextObject): + New methods, allow query of AccessibleEvent objects + for more context details (via the "any_data" member + of the Event struct, above). + + * cspi/spi.h: + Definitions for AccessibleEvent_getContextString + and AccessibleEvent_getContextObject. + + * cspi/spi_listener.h: + (InternalEvent): New struct. + + * cspi/spi_event.c: + (AccessibleEvent_getContextString): + (AccessibleEvent_getContextObject): + Implementations of new methods, for obtaining + additional context information from some event types. + + * cspi/spi_registry.c: + (SPI_registerGlobalEventListener): + Added mention of active-descendant-changed event in docs. + + * cspi/cspi-bonobo-listener.c: + (cspi_event): + Marshal the any into the AccessibleEvent via + InternalEvent. + + * libspi/spi-private.h: + #include + (spi_init_any_nil): + (spi_init_any_string): + (spi_init_any_object): + New convenience function declarations. + + * libspi/util.c: + (spi_init_any_nil): + (spi_init_any_string): + (spi_init_any_object): + New convenience function implementations. + + * registryd/deviceeventcontroller.c: + (spi_poll_dec_mouse_moved): + (spi_device_event_controller_forward_mous_event): + Initialize any_data member of event. + (spi_deregister_controller_device_listener): + Fix incorrect param pass which was preventing deregistration. + + * registryd/registry.c: + (desktop_add_application): + (desktop_remove_application): + Add object data to event's any_data before dispatch. + (parse_event_type): + Fix for error messages from GAIL. + + * test/event-listener-test.c: + Test new ContextString and "any_data" API: + (report_text_event): New method query and output context string. + (main): register a new text listener with report_text_event + callback. + 2002-11-19 Darren Kenny Fixes for bugs 98127 and 97914. @@ -76,9 +231,6 @@ * 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: diff --git a/atk-bridge/bridge.c b/atk-bridge/bridge.c index 21f47e0..4647011 100644 --- a/atk-bridge/bridge.c +++ b/atk-bridge/bridge.c @@ -43,6 +43,50 @@ static SpiApplication *this_app = NULL; static gboolean registry_died = FALSE; static guint toplevel_handler; +/* NOT YET USED + static GQuark atk_quark_property_changed_name; + static GQuark atk_quark_property_changed_description; + static GQuark atk_quark_property_changed_parent; + static GQuark atk_quark_property_changed_role; + static GQuark atk_quark_property_changed_table_caption; + static GQuark atk_quark_property_changed_table_column_description; + static GQuark atk_quark_property_changed_table_row_description; + static guint atk_signal_property_changed; +*/ + +static guint atk_signal_text_changed; +static guint atk_signal_child_changed; + +/* NOT YET USED + static guint atk_signal_text_selection_changed; + static guint atk_signal_active_descendant_changed; + static guint atk_signal_row_reordered; + static guint atk_signal_row_inserted; + static guint atk_signal_row_deleted; + static guint atk_signal_column_reordered; + static guint atk_signal_column_inserted; + static guint atk_signal_column_deleted; +*/ + +#define ATK_BRIDGE_RESERVED_CONTEXT_SIZE 16 + +typedef enum { + ATK_BRIDGE_CONTEXT_TYPE_NONE = 0, + ATK_BRIDGE_CONTEXT_TYPE_STRING, + ATK_BRIDGE_CONTEXT_TYPE_OBJECT +} AtkBridgeEventContextType; + +typedef union { + gchar *string; + AtkObject *object; + gpointer *foo; +} AtkBridgeEventContextData; + +typedef struct { + AtkBridgeEventContextType _type; + AtkBridgeEventContextData _data; +} AtkBridgeEventContext; + static Accessibility_Registry spi_atk_bridge_get_registry (void); static void spi_atk_bridge_do_registration (void); static void spi_atk_bridge_toplevel_added (AtkObject *object, @@ -90,6 +134,15 @@ static GArray *listener_ids = NULL; extern void gnome_accessibility_module_init (void); extern void gnome_accessibility_module_shutdown (void); +static void +atk_bridge_init_event_type_consts () +{ + atk_signal_child_changed = g_signal_lookup ("child_changed", + ATK_TYPE_OBJECT); + atk_signal_text_changed = g_signal_lookup ("text_changed", + ATK_TYPE_TEXT); +} + static int atk_bridge_init (gint *argc, gchar **argv[]) { @@ -122,6 +175,8 @@ atk_bridge_init (gint *argc, gchar **argv[]) { spi_atk_bridge_do_registration (); } + + atk_bridge_init_event_type_consts (); return 0; } @@ -371,6 +426,34 @@ gnome_accessibility_module_shutdown (void) } static void +atk_bridge_event_context_init (CORBA_any *any, + AtkBridgeEventContext *ctx) +{ + SpiAccessible *accessible; + if (ctx) + { + switch (ctx->_type) + { + /* FIXME + case ATK_BRIDGE_CONTEXT_TYPE_OBJECT: + accessible = spi_accessible_new (ctx->_data.object); + spi_init_any_object (any, BONOBO_OBJREF (accessible)); + break; + */ + case ATK_BRIDGE_CONTEXT_TYPE_STRING: + spi_init_any_string (any, &ctx->_data.string); + break; + default: + spi_init_any_nil (any); + } + } + else + { + spi_init_any_nil (any); + } +} + +static void spi_atk_bridge_focus_tracker (AtkObject *object) { SpiAccessible *source; @@ -382,7 +465,7 @@ spi_atk_bridge_focus_tracker (AtkObject *object) e.source = BONOBO_OBJREF (source); e.detail1 = 0; e.detail2 = 0; - + spi_init_any_nil (&e.any_data); Accessibility_Registry_notifyEvent (spi_atk_bridge_get_registry (), &e, &ev); if (BONOBO_EX (&ev)) registry_died = TRUE; @@ -391,10 +474,49 @@ spi_atk_bridge_focus_tracker (AtkObject *object) CORBA_exception_free (&ev); } +static +AtkBridgeEventContext * +spi_atk_bridge_event_context_create (GObject *gobject, + long detail1, + long detail2, + GSignalQuery *signal_query, + const gchar *detail) +{ + AtkBridgeEventContext *ctx = g_new0 (AtkBridgeEventContext, 1); + /* + if (signal_query->signal_id == atk_signal_child_changed) + { + ctx->_type = ATK_BRIDGE_CONTEXT_TYPE_OBJECT; + ctx->_data.object = atk_object_ref_accessible_child (ATK_OBJECT (gobject), + (gint) detail1); + } + else */ if (signal_query->signal_id == atk_signal_text_changed) + { + ctx->_type = ATK_BRIDGE_CONTEXT_TYPE_STRING; + ctx->_data.string = atk_text_get_text (ATK_TEXT (gobject), + (gint) detail1, + (gint) detail1+detail2); + } + else + { + ctx->_type = ATK_BRIDGE_CONTEXT_TYPE_NONE; + } + return ctx; +} + +static void +spi_atk_bridge_event_context_free (AtkBridgeEventContext *ctx) +{ + if (ctx->_type == ATK_BRIDGE_CONTEXT_TYPE_OBJECT) + g_object_unref (ctx->_data.object); + g_free (ctx); +} + static void -spi_atk_emit_eventv (GObject *gobject, - unsigned long detail1, - unsigned long detail2, +spi_atk_emit_eventv (GObject *gobject, + unsigned long detail1, + unsigned long detail2, + AtkBridgeEventContext *context, const char *format, ...) { va_list args; @@ -431,15 +553,16 @@ spi_atk_emit_eventv (GObject *gobject, e.source = BONOBO_OBJREF (source); e.detail1 = detail1; e.detail2 = detail2; - #ifdef SPI_BRIDGE_DEBUG s = Accessibility_Accessible__get_name (BONOBO_OBJREF (source), &ev); g_warning ("Emitting event '%s' (%lu, %lu) on %s", e.type, e.detail1, e.detail2, s); CORBA_free (s); #endif - + CORBA_exception_init (&ev); + atk_bridge_event_context_init (&e.any_data, context); Accessibility_Registry_notifyEvent (spi_atk_bridge_get_registry (), &e, &ev); + /* I haven't freed any_data._value when it's a char*, does it leak ? */ #ifdef SPI_BRIDGE_DEBUG if (ev._major != CORBA_NO_EXCEPTION) g_warning ("error emitting event %s, (%d) %s", @@ -487,7 +610,8 @@ spi_atk_bridge_property_event_listener (GSignalInvocationHint *signal_hint, gobject = g_value_get_object (param_values + 0); values = (AtkPropertyValues*) g_value_get_pointer (param_values + 1); - spi_atk_emit_eventv (gobject, 0, 0, "object:property-change:%s", values->property_name); + spi_atk_emit_eventv (gobject, 0, 0, NULL, + "object:property-change:%s", values->property_name); return TRUE; } @@ -520,6 +644,7 @@ spi_atk_bridge_state_event_listener (GSignalInvocationHint *signal_hint, spi_atk_emit_eventv (gobject, detail1, 0, + NULL, type); g_free (property_name); g_free (type); @@ -623,6 +748,7 @@ spi_atk_bridge_signal_listener (GSignalInvocationHint *signal_hint, GSignalQuery signal_query; const gchar *name; const gchar *detail; + AtkBridgeEventContext *ctx = NULL; gint detail1 = 0, detail2 = 0; #ifdef SPI_BRIDGE_DEBUG @@ -650,11 +776,22 @@ spi_atk_bridge_signal_listener (GSignalInvocationHint *signal_hint, detail1 = g_value_get_int (param_values + 1); if (G_VALUE_TYPE (param_values + 2) == G_TYPE_INT) detail2 = g_value_get_int (param_values + 2); - + + /* build some event context data, depending on the type */ + ctx = spi_atk_bridge_event_context_create (gobject, + detail1, detail2, + &signal_query, + detail); + if (detail) - spi_atk_emit_eventv (gobject, detail1, detail2, "object:%s:%s", name, detail); + spi_atk_emit_eventv (gobject, detail1, detail2, ctx, + "object:%s:%s", name, detail); else - spi_atk_emit_eventv (gobject, detail1, detail2, "object:%s", name); + spi_atk_emit_eventv (gobject, detail1, detail2, ctx, + "object:%s", name); + + if (ctx) + spi_atk_bridge_event_context_free (ctx); return TRUE; } @@ -667,9 +804,11 @@ spi_atk_bridge_window_event_listener (GSignalInvocationHint *signal_hint, { GObject *gobject; GSignalQuery signal_query; - const gchar *name; + AtkBridgeEventContext ctx; + + const gchar *name, *s; #ifdef SPI_BRIDGE_DEBUG - const gchar *s, *s2; + const gchar *s2; #endif g_signal_query (signal_hint->signal_id, &signal_query); @@ -682,9 +821,13 @@ spi_atk_bridge_window_event_listener (GSignalInvocationHint *signal_hint, fprintf (stderr, "Received signal %s:%s from object %s (gail %s)\n", g_type_name (signal_query.itype), name, s ? s : "" , s2); #endif - + gobject = g_value_get_object (param_values + 0); - spi_atk_emit_eventv (gobject, 0, 0, "window:%s", name); - + ctx._type = ATK_BRIDGE_CONTEXT_TYPE_STRING; + s = atk_object_get_name (ATK_OBJECT (gobject)); + ctx._data.string = (gchar *) s; + /* cast from const silences compiler */ + spi_atk_emit_eventv (gobject, 0, 0, &ctx, "window:%s", name); + /* don't free the context, it's on the stack */ return TRUE; } diff --git a/configure.in b/configure.in index b7aff56..c3e0b58 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=3 +AT_SPI_MICRO_VERSION=4 AT_SPI_INTERFACE_AGE=0 -AT_SPI_BINARY_AGE=3 +AT_SPI_BINARY_AGE=4 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) diff --git a/cspi/bonobo/cspi-bonobo-listener.c b/cspi/bonobo/cspi-bonobo-listener.c index 9a5eb32..afa7660 100644 --- a/cspi/bonobo/cspi-bonobo-listener.c +++ b/cspi/bonobo/cspi-bonobo-listener.c @@ -91,20 +91,21 @@ cspi_event (SpiEventListener *listener, { GList *l; CSpiEventListener *clistener = (CSpiEventListener *) listener; - AccessibleEvent aevent; + InternalEvent aevent; Accessible *source = cspi_object_borrow (event->source); - aevent.type = event->type; - aevent.source = source; - aevent.detail1 = event->detail1; - aevent.detail2 = event->detail2; + aevent.event.type = event->type; + aevent.event.source = source; + aevent.event.detail1 = event->detail1; + aevent.event.detail2 = event->detail2; + aevent.data = &event->any_data; /* FIXME: re-enterancy hazard on this list */ for (l = clistener->callbacks; l; l = l->next) { EventHandler *eh = l->data; - - eh->cb.event (&aevent, eh->user_data); + /* cast hides our private stuff from client handlers */ + eh->cb.event ((AccessibleEvent *) &aevent, eh->user_data); } cspi_object_return (source); diff --git a/cspi/spi-listener.h b/cspi/spi-listener.h index 63384f6..81029d7 100644 --- a/cspi/spi-listener.h +++ b/cspi/spi-listener.h @@ -39,6 +39,14 @@ typedef struct { long detail1; long detail2; } AccessibleEvent; + +/* + * For internal use by CSPI implementation only + */ +typedef struct { + AccessibleEvent event; + void *data; +} InternalEvent; typedef enum { SPI_KEY_PRESSED = 1<<0, diff --git a/cspi/spi.h b/cspi/spi.h index 5fb95eb..842599a 100644 --- a/cspi/spi.h +++ b/cspi/spi.h @@ -27,7 +27,7 @@ #include /* * Definitions for AccessibleRole, AccessibleState, - * AccessibleEvent, and event listeners. + * and event listeners. */ #include #include @@ -793,6 +793,14 @@ double AccessibleValue_getMaximumValue (AccessibleValue *obj); SPIBoolean AccessibleValue_setCurrentValue (AccessibleValue *obj, double newValue); +/* + * Prototypes for accessor functions, to obtain context + * information for accessible events. + */ + +char* AccessibleEvent_getContextString (const AccessibleEvent *e); +Accessible * AccessibleEvent_getContextObject (const AccessibleEvent *e); + /* Misc methods */ void SPI_freeString (char *s); diff --git a/cspi/spi_event.c b/cspi/spi_event.c index 5eb5c16..0d63ac9 100644 --- a/cspi/spi_event.c +++ b/cspi/spi_event.c @@ -326,3 +326,75 @@ AccessibleDeviceListener_unref (AccessibleDeviceListener *listener) { cspi_device_listener_unref (listener); } + +/** + * AccessibleEvent_getContextString: + * @event: a pointer to the #AccessibleEvent being queried. + * + * Queries an #AccessibleEvent for a string whose meaning depends + * on the event's context, that is, the event type and details. + * Not all events have context strings, in which case this + * query returns NULL. + * Context strings may be returned by: + * object:text-changed events, + * in which case they represent the text inserted or deleted; + * window: events, in which case they indicate the window title, + * or other events. + * + * Returns: the context string for the event, or %NULL if + * there is no context string for the event. + **/ +char * +AccessibleEvent_getContextString (const AccessibleEvent *e) +{ + InternalEvent *foo = (InternalEvent *) e; + CORBA_any *any; + g_return_val_if_fail (foo, NULL); + g_return_val_if_fail (foo->data, NULL); + any = (CORBA_any *) foo->data; + if (CORBA_TypeCode_equivalent (any->_type, TC_CORBA_string, NULL)) + { + return * (char **) any->_value; + } + else + { +#ifdef EVENT_CONTEXT_DEBUG + fprintf (stderr, "requested string, TC is not TC_CORBA_string! (%u)\n", + (unsigned) any->_type); +#endif + return NULL; + } +} + +/** + * AccessibleEvent_getContextObject: + * @event: a pointer to the #AccessibleEvent being queried. + * + * Queries an #AccessibleEvent for an #Accessible whose meaning depends + * on the event's context, that is, the event type and details. + * Not all events have context strings, in which case this + * query returns NULL. + * Context #Accessible objects may be returned by, for instance: + * object:child-changed events, + * in which case they represent the child added or deleted. + * Note that context #Accessibles are not guaranteed to outlive + * event delivery, in which case this call may return %NULL + * even if the object existed at the time of dispatch. + * + * Returns: the context #Accessible for the event, or %NULL if + * there is no context #Accessible object for the event. + **/ +Accessible * +AccessibleEvent_getContextObject (const AccessibleEvent *e) +{ + InternalEvent *foo = (InternalEvent *) e; + CORBA_any *any; + g_return_val_if_fail (foo, NULL); + g_return_val_if_fail (foo->data, NULL); + any = (CORBA_any *) foo->data; + if (any->_type == TC_CORBA_Object) + return cspi_object_add (* (CORBA_Object *) any->_value); + else + return NULL; +} + diff --git a/cspi/spi_registry.c b/cspi/spi_registry.c index e97ffc1..12978c0 100644 --- a/cspi/spi_registry.c +++ b/cspi/spi_registry.c @@ -70,6 +70,7 @@ * object:column-reordered * object:column-deleted * object:model-changed + * object:active-descendant-changed * * (window events) * @@ -545,6 +546,7 @@ SPI_deregisterDeviceEventListener (AccessibleDeviceListener *listener, Accessibility_ControllerEventMask controller_event_mask; Accessibility_DeviceEventController device_event_controller; Accessibility_EventTypeSeq event_types; + Accessibility_EventType event_type_buff[2]; if (!listener) { @@ -556,7 +558,7 @@ SPI_deregisterDeviceEventListener (AccessibleDeviceListener *listener, cspi_return_val_if_ev ("getting keystroke listener", FALSE); - event_types._buffer = Accessibility_EventTypeSeq_allocbuf (2); + event_types._buffer = event_type_buff; event_types._length = 2; event_types._buffer[0] = Accessibility_BUTTON_PRESSED_EVENT; event_types._buffer[1] = Accessibility_BUTTON_RELEASED_EVENT; diff --git a/idl/Accessibility_Action.idl b/idl/Accessibility_Action.idl index cbb1ea8..2bab51d 100644 --- a/idl/Accessibility_Action.idl +++ b/idl/Accessibility_Action.idl @@ -84,6 +84,8 @@ module Accessibility { */ void unImplemented (); void unImplemented2 (); + void unImplemented3 (); + void unImplemented4 (); }; }; diff --git a/idl/Accessibility_Component.idl b/idl/Accessibility_Component.idl index c3ca89f..b444ab1 100644 --- a/idl/Accessibility_Component.idl +++ b/idl/Accessibility_Component.idl @@ -56,5 +56,7 @@ module Accessibility { */ void unImplemented (); void unImplemented2 (); + void unImplemented3 (); + void unImplemented4 (); }; }; diff --git a/idl/Accessibility_Desktop.idl b/idl/Accessibility_Desktop.idl index 69a7aa2..9c398f9 100644 --- a/idl/Accessibility_Desktop.idl +++ b/idl/Accessibility_Desktop.idl @@ -39,6 +39,8 @@ module Accessibility { */ void unImplemented_ (); void unImplemented2_ (); + void unImplemented3_ (); + void unImplemented4_ (); }; }; diff --git a/idl/Accessibility_EditableText.idl b/idl/Accessibility_EditableText.idl index eb9cd54..5e39f27 100644 --- a/idl/Accessibility_EditableText.idl +++ b/idl/Accessibility_EditableText.idl @@ -34,7 +34,7 @@ module Accessibility { boolean deleteText (in long startPos, in long endPos); boolean pasteText (in long position); /** - * unImplemented5: + * unImplemented7: * * placeholders for future expansion. Note that these are named * 'unimplemented5 and unimplemented6' to avoid conflict with @@ -42,5 +42,9 @@ module Accessibility { */ void unImplemented5 (); void unImplemented6 (); + void unImplemented9 (); + void unImplemented10 (); + void unImplemented11 (); + void unImplemented12 (); }; }; diff --git a/idl/Accessibility_Event.idl b/idl/Accessibility_Event.idl index 23c66fa..792fa44 100644 --- a/idl/Accessibility_Event.idl +++ b/idl/Accessibility_Event.idl @@ -34,6 +34,7 @@ module Accessibility Accessible source; long detail1; long detail2; + any any_data; }; interface EventListener : Bonobo::Unknown { diff --git a/idl/Accessibility_Hyperlink.idl b/idl/Accessibility_Hyperlink.idl index 95697cb..3c45f5d 100644 --- a/idl/Accessibility_Hyperlink.idl +++ b/idl/Accessibility_Hyperlink.idl @@ -38,5 +38,7 @@ module Accessibility { */ void unImplemented (); void unImplemented2 (); + void unImplemented3 (); + void unImplemented4 (); }; }; diff --git a/idl/Accessibility_Image.idl b/idl/Accessibility_Image.idl index f784f22..54df08d 100644 --- a/idl/Accessibility_Image.idl +++ b/idl/Accessibility_Image.idl @@ -34,5 +34,7 @@ module Accessibility { */ void unImplemented (); void unImplemented2 (); + void unImplemented3 (); + void unImplemented4 (); }; }; diff --git a/idl/Accessibility_Registry.idl b/idl/Accessibility_Registry.idl index 46fb458..295d45d 100644 --- a/idl/Accessibility_Registry.idl +++ b/idl/Accessibility_Registry.idl @@ -151,6 +151,10 @@ module Accessibility { */ void unImplemented (); void unImplemented2 (); + void unImplemented3 (); + void unImplemented4 (); + void unImplemented5 (); + void unImplemented6 (); }; /* Deprecated, DO NOT USE! */ @@ -220,6 +224,8 @@ module Accessibility { void unImplemented_2_ (); void unImplemented_3_ (); void unImplemented_4_ (); + void unImplemented_5_ (); + void unImplemented_6_ (); }; interface DeviceEventController : Bonobo::Unknown { @@ -342,6 +348,8 @@ module Accessibility { */ void unImplemented (); void unImplemented2 (); + void unImplemented3 (); + void unImplemented4 (); }; }; diff --git a/idl/Accessibility_Relation.idl b/idl/Accessibility_Relation.idl index 9c6c076..55bf83d 100644 --- a/idl/Accessibility_Relation.idl +++ b/idl/Accessibility_Relation.idl @@ -55,6 +55,8 @@ module Accessibility { /* placeholders for future expansion */ void unImplemented (); void unImplemented2 (); + void unImplemented3 (); + void unImplemented4 (); }; }; diff --git a/idl/Accessibility_Selection.idl b/idl/Accessibility_Selection.idl index a5cad01..a14e505 100644 --- a/idl/Accessibility_Selection.idl +++ b/idl/Accessibility_Selection.idl @@ -40,5 +40,7 @@ module Accessibility { */ void unImplemented (); void unImplemented2 (); + void unImplemented3 (); + void unImplemented4 (); }; }; diff --git a/idl/Accessibility_State.idl b/idl/Accessibility_State.idl index be5f398..eea5ab5 100644 --- a/idl/Accessibility_State.idl +++ b/idl/Accessibility_State.idl @@ -140,6 +140,8 @@ module Accessibility { */ void unImplemented (); void unImplemented2 (); + void unImplemented3 (); + void unImplemented4 (); }; }; diff --git a/idl/Accessibility_Table.idl b/idl/Accessibility_Table.idl index 95103a0..66e0301 100644 --- a/idl/Accessibility_Table.idl +++ b/idl/Accessibility_Table.idl @@ -62,5 +62,9 @@ typedef sequence LongSeq; void unImplemented2 (); void unImplemented3 (); void unImplemented4 (); + void unImplemented5 (); + void unImplemented6 (); + void unImplemented7 (); + void unImplemented8 (); }; }; diff --git a/idl/Accessibility_Text.idl b/idl/Accessibility_Text.idl index c733538..268eb35 100644 --- a/idl/Accessibility_Text.idl +++ b/idl/Accessibility_Text.idl @@ -64,5 +64,7 @@ module Accessibility { void unImplemented2 (); void unImplemented3 (); void unImplemented4 (); + void unImplemented7 (); + void unImplemented8 (); }; }; diff --git a/idl/Accessibility_Value.idl b/idl/Accessibility_Value.idl index 92afd62..82de771 100644 --- a/idl/Accessibility_Value.idl +++ b/idl/Accessibility_Value.idl @@ -35,5 +35,7 @@ module Accessibility { */ void unImplemented (); void unImplemented2 (); + void unImplemented3 (); + void unImplemented4 (); }; }; diff --git a/libspi/application.c b/libspi/application.c index 8bf3294..32f8f90 100644 --- a/libspi/application.c +++ b/libspi/application.c @@ -182,7 +182,7 @@ spi_application_object_event_listener (GSignalInvocationHint *signal_hint, e.source = CORBA_OBJECT_NIL; e.detail1 = 0; e.detail2 = 0; - + spi_init_any_nil (&e.any_data); notify_listeners (the_app->toolkit_listeners, source, &e); bonobo_object_unref (BONOBO_OBJECT (source)); @@ -224,6 +224,7 @@ spi_application_toolkit_event_listener (GSignalInvocationHint *signal_hint, e.source = CORBA_OBJECT_NIL; e.detail1 = 0; e.detail2 = 0; + spi_init_any_nil (&e.any_data); notify_listeners (the_app->toolkit_listeners, source, &e); bonobo_object_unref (BONOBO_OBJECT (source)); diff --git a/libspi/keystrokelistener.c b/libspi/keystrokelistener.c deleted file mode 100644 index 5358378..0000000 --- a/libspi/keystrokelistener.c +++ /dev/null @@ -1,146 +0,0 @@ -/* - * 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. - */ - -/* keystrokelistener.c: implement the KeystrokeListener interface */ - -#include -#ifdef SPI_DEBUG -# include -#endif -#include -#include - -/* Our parent Gtk object type */ -#define PARENT_TYPE BONOBO_TYPE_OBJECT - -enum { - KEY_EVENT, - LAST_SIGNAL -}; -static guint signals [LAST_SIGNAL]; - -/* - * CORBA Accessibility::KeystrokeListener::keyEvent method implementation - */ -static CORBA_boolean -impl_key_event (PortableServer_Servant servant, - const Accessibility_DeviceEvent *key, - CORBA_Environment *ev) -{ - gboolean was_consumed = FALSE; - SpiKeystrokeListener *listener = SPI_KEYSTROKE_LISTENER ( - bonobo_object_from_servant (servant)); - - g_signal_emit (G_OBJECT (listener), signals [KEY_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_keystroke_listener_class_init (SpiKeystrokeListenerClass *klass) -{ - POA_Accessibility_DeviceEventListener__epv *epv = &klass->epv; - - signals [KEY_EVENT] = g_signal_new ( - "key_event", - G_TYPE_FROM_CLASS (klass), - G_SIGNAL_RUN_LAST, - G_STRUCT_OFFSET (SpiKeystrokeListenerClass, key_event), - boolean_handled_accumulator, NULL, - marshal_BOOLEAN__POINTER, - G_TYPE_BOOLEAN, 1, G_TYPE_POINTER); - - epv->notifyEvent = impl_key_event; -} - -static void -spi_keystroke_listener_init (SpiKeystrokeListener *keystroke_listener) -{ -} - -BONOBO_TYPE_FUNC_FULL (SpiKeystrokeListener, - Accessibility_DeviceEventListener, - BONOBO_TYPE_OBJECT, - spi_keystroke_listener); - -SpiKeystrokeListener * -spi_keystroke_listener_new (void) -{ - SpiKeystrokeListener *retval = g_object_new ( - SPI_KEYSTROKE_LISTENER_TYPE, NULL); - return retval; -} diff --git a/libspi/spi-private.h b/libspi/spi-private.h index 9ec3b9d..f10f10e 100644 --- a/libspi/spi-private.h +++ b/libspi/spi-private.h @@ -25,6 +25,7 @@ #define SPI_PRIVATE_H_ #include +#include G_BEGIN_DECLS @@ -40,6 +41,9 @@ void spi_re_entrant_list_delete_link (GList * const *element_ptr); void spi_re_entrant_list_foreach (GList **list, SpiReEntrantFn func, gpointer user_data); +void spi_init_any_nil (CORBA_any *any); +void spi_init_any_string (CORBA_any *any, char **string); +void spi_init_any_object (CORBA_any *any, CORBA_Object o); G_END_DECLS diff --git a/libspi/util.c b/libspi/util.c index 99d1404..ad4f465 100644 --- a/libspi/util.c +++ b/libspi/util.c @@ -33,6 +33,8 @@ typedef struct { static GSList *working_list = NULL; /* of Iteration */ +static char *spi_atk_bridge_null_string = ""; + /* * deletes an element from the list - in a re-entrant * safe fashion; advances the element pointer to the next @@ -81,7 +83,7 @@ spi_re_entrant_list_foreach (GList **list, { Iteration i; - if (!list) + if (!list || !*list) { return; } @@ -102,3 +104,33 @@ spi_re_entrant_list_foreach (GList **list, working_list = g_slist_remove (working_list, &i); } + +void +spi_init_any_nil (CORBA_any *any) +{ + any->_type = TC_null; + any->_value = NULL; + any->_release = FALSE; +} + +void +spi_init_any_object (CORBA_any *any, CORBA_Object o) +{ + CORBA_Environment ev; + CORBA_exception_init (&ev); + any->_type = TC_CORBA_Object; + any->_value = CORBA_Object_duplicate (o, &ev); + any->_release = FALSE; + CORBA_exception_free (&ev); +} + +void +spi_init_any_string (CORBA_any *any, char **string_pointer) +{ + any->_type = (CORBA_TypeCode) TC_CORBA_string; + if (string_pointer && *string_pointer) + any->_value = string_pointer; + else + any->_value = &spi_atk_bridge_null_string; + any->_release = FALSE; +} diff --git a/registryd/deviceeventcontroller.c b/registryd/deviceeventcontroller.c index 600c3d4..098eb7d 100644 --- a/registryd/deviceeventcontroller.c +++ b/registryd/deviceeventcontroller.c @@ -53,7 +53,8 @@ /* A pointer to our parent object class */ static GObjectClass *spi_device_event_controller_parent_class; static int spi_error_code = 0; -static GdkPoint *last_mouse_pos = NULL; +static GdkPoint last_mouse_pos_static = {0, 0}; +static GdkPoint *last_mouse_pos = &last_mouse_pos_static; static unsigned int mouse_mask_state = 0; static unsigned int mouse_button_mask = Button1Mask | Button2Mask | Button3Mask | Button4Mask | Button5Mask; @@ -238,18 +239,17 @@ spi_dec_poll_mouse_moved (gpointer data) mouse_e.modifiers = (CORBA_unsigned_short) mouse_mask_state; mouse_e.timestamp = 0; - mouse_e.event_string = CORBA_string_dup (""); + mouse_e.event_string = ""; 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; + spi_init_any_nil (&e.any_data); CORBA_exception_init (&ev); if (!is_consumed) Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry), @@ -266,6 +266,7 @@ spi_dec_poll_mouse_moved (gpointer data) e.source = BONOBO_OBJREF (registry->desktop); e.detail1 = mouse_mask_state; e.detail2 = mask_return; + spi_init_any_nil (&e.any_data); CORBA_exception_init (&ev); Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry), &e, @@ -273,17 +274,13 @@ spi_dec_poll_mouse_moved (gpointer data) } mouse_mask_state = mask_return; } - if (last_mouse_pos == NULL) { - last_mouse_pos = g_new0 (GdkPoint, 1); - last_mouse_pos->x = 0; - last_mouse_pos->y = 0; - } if (poll_count++ == poll_count_modulus) { poll_count = 0; e.type = "mouse:abs"; e.source = BONOBO_OBJREF (registry->desktop); e.detail1 = x; e.detail2 = y; + spi_init_any_nil (&e.any_data); CORBA_exception_init (&ev); Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry), &e, @@ -294,6 +291,7 @@ spi_dec_poll_mouse_moved (gpointer data) e.source = BONOBO_OBJREF (registry->desktop); e.detail1 = x - last_mouse_pos->x; e.detail2 = y - last_mouse_pos->y; + spi_init_any_nil (&e.any_data); CORBA_exception_init (&ev); last_mouse_pos->x = x; last_mouse_pos->y = y; @@ -333,12 +331,10 @@ static int spi_dec_ungrab_mouse (gpointer data) { Display *display = spi_get_display (); - fprintf (stderr, "mouse ungrab : display = %p\n", display); if (display) { XUngrabButton (spi_get_display (), AnyButton, AnyModifier, XDefaultRootWindow (spi_get_display ())); - fprintf (stderr, "mouse grab released\n"); } return FALSE; } @@ -650,11 +646,8 @@ spi_controller_notify_mouselisteners (SpiDEController *controlle 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; @@ -737,15 +730,15 @@ spi_device_event_controller_forward_mouse_event (SpiDEController *controller, 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.event_string = ""; 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; + spi_init_any_nil (&e.any_data); CORBA_exception_init (&ev); Accessibility_Registry_notifyEvent (BONOBO_OBJREF (controller->registry), @@ -801,8 +794,10 @@ global_filter_fn (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) if (priv->pending_xkb_mod_relatch_mask) { unsigned int feedback_mask; +#ifdef SPI_XKB_DEBUG fprintf (stderr, "relatching %x\n", priv->pending_xkb_mod_relatch_mask); +#endif /* temporarily turn off the latch bell, if it's on */ XkbGetControls (display, XkbAccessXFeedbackMask, @@ -827,8 +822,10 @@ global_filter_fn (GdkXEvent *gdk_xevent, GdkEvent *event, gpointer data) priv->xkb_desc->ctrls->ax_options = feedback_mask; XkbChangeControls (display, priv->xkb_desc, &changes); } +#ifdef SPI_XKB_DEBUG fprintf (stderr, "relatched %x\n", priv->pending_xkb_mod_relatch_mask); +#endif priv->pending_xkb_mod_relatch_mask = 0; } } @@ -1412,8 +1409,13 @@ spi_deregister_controller_device_listener (SpiDEController *controlle DEControllerListener *listener, CORBA_Environment *ev) { + RemoveListenerClosure ctx; + + ctx.ev = ev; + ctx.listener = listener; + spi_re_entrant_list_foreach (&controller->mouse_listeners, - remove_listener_cb, listener); + remove_listener_cb, &ctx); } static void @@ -1582,7 +1584,6 @@ dec_synth_keycode_press (SpiDEController *controller, #endif } } - fprintf (stderr, "press %d\n", (int) keycode); XTestFakeKeyEvent (spi_get_display (), keycode, True, time); priv->last_press_keycode = keycode; XSync (spi_get_display (), False); @@ -1626,7 +1627,6 @@ dec_synth_keycode_release (SpiDEController *controller, #endif } } - fprintf (stderr, "release %d\n", (int) keycode); XTestFakeKeyEvent (spi_get_display (), keycode, False, time); priv->last_release_keycode = keycode; XSync (spi_get_display (), False); @@ -1709,7 +1709,6 @@ impl_generate_mouse_event (PortableServer_Servant servant, fprintf (stderr, "generating mouse %s event at %ld, %ld\n", eventName, (long int) x, (long int) y); #endif - g_message ("mouse event synthesis\n"); switch (eventName[0]) { case 'b': diff --git a/registryd/registry.c b/registryd/registry.c index c00365a..c1acfb1 100644 --- a/registryd/registry.c +++ b/registryd/registry.c @@ -89,12 +89,20 @@ desktop_add_application (SpiDesktop *desktop, BonoboObject *registry = BONOBO_OBJECT (data); Accessibility_Event e; CORBA_Environment ev; + Accessibility_Accessible a; + CORBA_exception_init (&ev); e.type = "object:children-changed:add"; e.source = BONOBO_OBJREF (desktop); e.detail1 = index; e.detail2 = 0; - CORBA_exception_init (&ev); + a = Accessibility_Accessible_getChildAtIndex (BONOBO_OBJREF (desktop), + index, &ev); + /* FIXME + spi_init_any_object (&e.any_data, a); + */ + spi_init_any_nil (&e.any_data); + Accessibility_Accessible_unref (a, &ev); Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry), &e, &ev); Accessibility_Desktop_unref (e.source, &ev); @@ -109,13 +117,22 @@ desktop_remove_application (SpiDesktop *desktop, { BonoboObject *registry = BONOBO_OBJECT (data); Accessibility_Event e; + Accessibility_Accessible a; CORBA_Environment ev; + CORBA_exception_init (&ev); + e.type = "object:children-changed:remove"; e.source = BONOBO_OBJREF (desktop); e.detail1 = index; e.detail2 = 0; - CORBA_exception_init (&ev); + a = Accessibility_Accessible_getChildAtIndex (BONOBO_OBJREF (desktop), + index, &ev); + /* FIXME + spi_init_any_object (&e.any_data, a); + */ + spi_init_any_nil (&e.any_data); + Accessibility_Accessible_unref (a, &ev); Accessibility_Registry_notifyEvent (BONOBO_OBJREF (registry), &e, &ev); Accessibility_Desktop_unref (e.source, &ev); @@ -259,6 +276,10 @@ parse_event_type (EventTypeStruct *etype, const char *event_name) { etype->type_cat = ETYPE_WINDOW; } + else if (!g_ascii_strncasecmp (event_name, "keyboard:", 9)) + { + etype->type_cat = ETYPE_KEYBOARD; + } else { etype->type_cat = ETYPE_TOOLKIT; @@ -363,7 +384,6 @@ impl_accessibility_registry_register_global_event_listener ( GList **list; #ifdef SPI_LISTENER_DEBUG - fprintf (stderr, "registering"); fprintf (stderr, "registering for events of type %s\n", event_name); #endif @@ -575,7 +595,6 @@ notify_listeners_cb (GList * const *list, gpointer user_data) #endif ctx->e_out.source = CORBA_Object_duplicate (ctx->source, ctx->ev); - if (BONOBO_EX (ctx->ev)) { return SPI_RE_ENTRANT_CONTINUE; @@ -620,15 +639,14 @@ impl_registry_notify_event (PortableServer_Servant servant, list = get_listener_list (registry, ctx.etype.type_cat); - if (list) + if (list && *list) { ctx.ev = ev; ctx.e_out = *e; + CORBA_any__copy (&ctx.e_out.any_data, &e->any_data); ctx.source = e->source; - spi_re_entrant_list_foreach (list, notify_listeners_cb, &ctx); } - } static void @@ -657,6 +675,8 @@ spi_registry_class_init (SpiRegistryClass *klass) static void spi_registry_init (SpiRegistry *registry) { + fprintf (stderr, "REGISTRY INITIALIZED: toolkit list = %p\n", + ®istry->toolkit_listeners); registry->object_listeners = NULL; registry->window_listeners = NULL; registry->toolkit_listeners = NULL; diff --git a/test/event-listener-test.c b/test/event-listener-test.c index a729124..c3374b0 100644 --- a/test/event-listener-test.c +++ b/test/event-listener-test.c @@ -29,12 +29,14 @@ 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 report_text_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 AccessibleEventListener *text_listener; static AccessibleDeviceListener *mouse_device_listener; static gint n_elements_traversed = 0; static GTimer *timer; @@ -80,12 +82,16 @@ main (int argc, char **argv) } } + fprintf (stderr, "RUNNING\n"); + SPI_init (); generic_listener = SPI_createAccessibleEventListener ( report_event, NULL); specific_listener = SPI_createAccessibleEventListener ( report_detail_event, NULL); + text_listener = SPI_createAccessibleEventListener ( + report_text_event, NULL); test_listener = SPI_createAccessibleEventListener ( timing_test_event, NULL); mouse_device_listener = SPI_createAccessibleDeviceListener ( @@ -129,7 +135,7 @@ main (int argc, char **argv) SPI_registerGlobalEventListener (generic_listener, "object:text-caret-moved"); - SPI_registerGlobalEventListener (generic_listener, + SPI_registerGlobalEventListener (text_listener, "object:text-changed"); SPI_registerGlobalEventListener (generic_listener, "object:column-inserted"); @@ -262,6 +268,17 @@ report_detail_event (const AccessibleEvent *event, void *user_data) if (s) SPI_freeString (s); } +void +report_text_event (const AccessibleEvent *event, void *user_data) +{ + char *s = Accessible_getName (event->source); + fprintf (stderr, "(detail) %s %s %d %d\n", event->type, s, + event->detail1, event->detail2); + if (s) SPI_freeString (s); + s = AccessibleEvent_getContextString (event); + fprintf (stderr, "context string %s\n", (s) ? s : ""); +} + SPIBoolean report_mouse_event (const AccessibleDeviceEvent *event, void *user_data) {