From 7ff7c0d0b863f7346f21e03b6d170e8c7c6f9878 Mon Sep 17 00:00:00 2001 From: billh Date: Fri, 19 Oct 2001 16:05:07 +0000 Subject: [PATCH] Added implementations for AtkObject:property-change support. Fixed some (but not all) ref counting bugs, and we now listen to selection-change events in simple-at.c. Considerable rework in the event handling in the bridge and elsewhere. Added Accessibility_Application_registerObjectEventListener(), which is used by the registry. Worked around a logjam by omitting an unref() in event listeners, which probably means that there is now a memory leak... will keep investigating. Mostly works but can still sometimes lock up on application exit if one leans on the app hard enough. git-svn-id: http://svn.gnome.org/svn/at-spi/trunk@79 e2bd861d-eb25-0410-b326-f6ed22b6b98c --- ChangeLog | 67 +++++++++++- at-bridge/bridge.c | 143 ++++++++++++++++++++++++-- atk-bridge/bridge.c | 143 ++++++++++++++++++++++++-- cspi/spi-impl.h | 1 + cspi/spi-util.c | 29 ++++++ cspi/spi.c | 8 +- cspi/spi.h | 2 +- cspi/spi_accessible.c | 154 +++++++++++++++++++++------- cspi/spi_component.c | 19 ++-- cspi/spi_selection.c | 7 +- cspi/spi_table.c | 4 +- cspi/spi_text.c | 15 ++- idl/Accessibility_Application.idl | 9 +- idl/Application.idl | 9 +- libspi/accessible.c | 28 ++---- libspi/accessibleeventlistener.c | 2 +- libspi/action.h | 2 +- libspi/application.c | 207 ++++++++++++++++++++++++++++++++++---- libspi/application.h | 3 + libspi/component.c | 6 +- libspi/editabletext.c | 17 ++-- libspi/eventlistener.c | 2 +- libspi/registry.c | 59 ++++++----- libspi/registry.h | 2 +- libspi/selection.c | 38 +++++-- libspi/selection.h | 2 +- libspi/table.c | 10 +- libspi/text.c | 73 +++++++++----- libspi/text.h | 4 +- registryd/registry.c | 59 ++++++----- registryd/registry.h | 2 +- test/at.c | 1 - test/simple-at.c | 72 +++++++++---- 33 files changed, 963 insertions(+), 236 deletions(-) diff --git a/ChangeLog b/ChangeLog index bd9c187..4466084 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,62 @@ +<2001-10-09 Bill Haneman + + * at-bridge/bridge.c: + Re-worked listeners for toolkit events, now we have signal + and property listeners. Added a private method + register_atk_event_listeners(), which registers with the + various atk and gtk signals we need to monitor in order to emit + our at-spi events. + Added emission hook for AtkObject:property-change events, to + support the 'property listeners'. + Fixed some alloc()s of Accessibility_Event structs to use CORBA + allocation. + + * cspi/spi-util.c: added methods spi_warn_ev and spi_check_ev, + which emit warnings and exit, respectively, if CORBA errors occur + during remote calls, and we now use these methods to check most of + our CORBA calls in the C bindings. + + * cspi/spi_accessible.c: + Changed AccessibleSelection_refSelectedChild() to + AccessibleSelection_getSelectedChild(), since all our cspi 'gets' + now increment refcounts. + + * cspi/spi_component.c: + Fixed some long pointer casts (dangerous!) to pass pointers to + CORBA_longs of the proper type to the CORBA stubs, and copy the + data into the longs that were passed into the C bindings code. + + * at-bridge/bridge.c: + + * libspi/accessible.c: + Removed ATK_IS_HYPERLINK() query, since AtkObjects are never + hyperlinks, AtkHyperlink is an object type. + + * libspi/application.c: + Added various conversions to and from "generic" event types and + atk-specific types; this is really part of the 'bridge' + implementation but is valid for all AtkObject-based accessibility + implementations. + + * libspi/editabletext.c: + Fixed nasty bug wherein editable text's finalize method was + unref'ing tha AtkObject reference that the text parent class was + about to unref _again_. There was also a nasty inheritance bug + that meant that the AccessibleEditableText class was corrupt. + + * libspi/selection.c: + Provided implementations for some selection API that was broken. + + * idl/Application.idl: + Added registerObjectEventListener () method. + + * THROUGHOUT: + Fixed a number of return values that were Bonobo_Unknowns from + bonobo_object_corba_objref(), which I + forgot to dup before returning. Changed instances of + bonobo_object_corba_objref (bonobo_object(o)) to + BONOBO_OBJREF(o), for concision and clarity. + <2001-10-13 Louise Miller * idl/Accessible.idl, idl/Application.idl, idl/Desktop.idl, @@ -6,10 +65,12 @@ of Bonobo.idl <2001-09-10 Marc Mulcahy + * libspi/component.c libspi/component.h: + Fixed typo. Added assertions for object checks in + AccessibleComponent code. + +<2001-10-09 Bill Haneman * idl/Accessible.idl: Added 'isEqual (Accessible *object)' diff --git a/at-bridge/bridge.c b/at-bridge/bridge.c index d4e1345..f47d084 100644 --- a/at-bridge/bridge.c +++ b/at-bridge/bridge.c @@ -30,6 +30,8 @@ #include "accessible.h" #include "application.h" +#define APP_STATIC_BUFF_SZ 64 + typedef struct _ArgStruct ArgStruct; struct _ArgStruct { @@ -44,6 +46,16 @@ static Application *this_app; static gboolean bridge_register_app (gpointer p); static void bridge_focus_tracker (AtkObject *object); static void bridge_exit_func(void); +static gboolean bridge_register_event_listener (); +static void register_atk_event_listeners(); +static gboolean bridge_property_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, + gpointer data); int gtk_module_init(gint *argc, gchar **argv[]) @@ -95,21 +107,37 @@ bridge_register_app (gpointer gp) bonobo_activate (); - /* Register for focus event notifications, and register app with central registry */ - atk_add_focus_tracker (bridge_focus_tracker); - Accessibility_Registry_registerApplication (registry, - bonobo_object_corba_objref (bonobo_object (this_app)), + CORBA_Object_duplicate (BONOBO_OBJREF (this_app), &ev), &ev); + + register_atk_event_listeners (); + return FALSE; } +static void +register_atk_event_listeners () +{ + /* Register for focus event notifications, and register app with central registry */ + +/* kludge to make sure the Atk interface types are registered, otherwise + the AtkText signal handlers below won't get registered */ + + ATK_TYPE_TEXT; + + 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:AtkText:text-changed"); + atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkText:text-caret-moved");*/ +} + static void bridge_exit_func() { fprintf (stderr, "exiting bridge\n"); Accessibility_Registry_deregisterApplication (registry, - bonobo_object_corba_objref ( - bonobo_object (this_app)), + CORBA_Object_duplicate (BONOBO_OBJREF (this_app), &ev), &ev); fprintf (stderr, "bridge exit func complete.\n"); } @@ -118,11 +146,110 @@ static void bridge_focus_tracker (AtkObject *object) { Accessibility_Event *e = Accessibility_Event__alloc(); e->type = CORBA_string_dup ("focus:"); - e->source = bonobo_object_corba_objref (bonobo_object (accessible_new (object))); + e->source = CORBA_Object_duplicate (BONOBO_OBJREF (accessible_new (object)), &ev); + e->detail1 = 0; + e->detail2 = 0; + Accessibility_Registry_notifyEvent (registry, e, &ev); +} + +static gboolean +bridge_property_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 (property) 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 (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 (accessible_new (aobject)), &ev); + } + else + { + g_error("received property-change event from non-AtkImplementor"); + } + + snprintf(sbuf, APP_STATIC_BUFF_SZ, "object:property-change:%s", values->property_name); + e->type = CORBA_string_dup (sbuf); + e->source = source; + e->detail1 = 0; + e->detail2 = 0; + if (source) + Accessibility_Registry_notifyEvent (registry, e, &ev); + return TRUE; +} + +static gboolean +bridge_signal_listener (GSignalInvocationHint *signal_hint, + guint n_param_values, + const GValue *param_values, + gpointer data) +{ + Accessibility_Event *e = g_new0(Accessibility_Event, 1); + AtkObject *aobject; + Bonobo_Unknown source; + 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 (property) signal %s:%s\n", + g_type_name (signal_query.itype), name); +#endif + gobject = g_value_get_object (param_values + 0); + + /* notify the actual listeners */ + if (ATK_IS_IMPLEMENTOR (gobject)) + { + aobject = atk_implementor_ref_accessible (ATK_IMPLEMENTOR (gobject)); + } + else if (ATK_IS_OBJECT (gobject)) + { + aobject = ATK_OBJECT (gobject); + g_object_ref (aobject); + } + else + { + g_error("received property-change event from non-AtkImplementor"); + } + + snprintf(sbuf, APP_STATIC_BUFF_SZ, "%s:%s", name, g_type_name (signal_query.itype)); + source = CORBA_Object_duplicate (BONOBO_OBJREF (accessible_new (aobject)), &ev); + e->type = CORBA_string_dup (sbuf); + e->source = source; e->detail1 = 0; e->detail2 = 0; Accessibility_Registry_notifyEvent (registry, e, &ev); - /* CORBA_free (e); */ + g_object_unref (aobject); + return TRUE; } static Accessibility_Registry bridge_get_registry () diff --git a/atk-bridge/bridge.c b/atk-bridge/bridge.c index d4e1345..f47d084 100644 --- a/atk-bridge/bridge.c +++ b/atk-bridge/bridge.c @@ -30,6 +30,8 @@ #include "accessible.h" #include "application.h" +#define APP_STATIC_BUFF_SZ 64 + typedef struct _ArgStruct ArgStruct; struct _ArgStruct { @@ -44,6 +46,16 @@ static Application *this_app; static gboolean bridge_register_app (gpointer p); static void bridge_focus_tracker (AtkObject *object); static void bridge_exit_func(void); +static gboolean bridge_register_event_listener (); +static void register_atk_event_listeners(); +static gboolean bridge_property_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, + gpointer data); int gtk_module_init(gint *argc, gchar **argv[]) @@ -95,21 +107,37 @@ bridge_register_app (gpointer gp) bonobo_activate (); - /* Register for focus event notifications, and register app with central registry */ - atk_add_focus_tracker (bridge_focus_tracker); - Accessibility_Registry_registerApplication (registry, - bonobo_object_corba_objref (bonobo_object (this_app)), + CORBA_Object_duplicate (BONOBO_OBJREF (this_app), &ev), &ev); + + register_atk_event_listeners (); + return FALSE; } +static void +register_atk_event_listeners () +{ + /* Register for focus event notifications, and register app with central registry */ + +/* kludge to make sure the Atk interface types are registered, otherwise + the AtkText signal handlers below won't get registered */ + + ATK_TYPE_TEXT; + + 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:AtkText:text-changed"); + atk_add_global_event_listener (bridge_signal_listener, "Gtk:AtkText:text-caret-moved");*/ +} + static void bridge_exit_func() { fprintf (stderr, "exiting bridge\n"); Accessibility_Registry_deregisterApplication (registry, - bonobo_object_corba_objref ( - bonobo_object (this_app)), + CORBA_Object_duplicate (BONOBO_OBJREF (this_app), &ev), &ev); fprintf (stderr, "bridge exit func complete.\n"); } @@ -118,11 +146,110 @@ static void bridge_focus_tracker (AtkObject *object) { Accessibility_Event *e = Accessibility_Event__alloc(); e->type = CORBA_string_dup ("focus:"); - e->source = bonobo_object_corba_objref (bonobo_object (accessible_new (object))); + e->source = CORBA_Object_duplicate (BONOBO_OBJREF (accessible_new (object)), &ev); + e->detail1 = 0; + e->detail2 = 0; + Accessibility_Registry_notifyEvent (registry, e, &ev); +} + +static gboolean +bridge_property_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 (property) 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 (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 (accessible_new (aobject)), &ev); + } + else + { + g_error("received property-change event from non-AtkImplementor"); + } + + snprintf(sbuf, APP_STATIC_BUFF_SZ, "object:property-change:%s", values->property_name); + e->type = CORBA_string_dup (sbuf); + e->source = source; + e->detail1 = 0; + e->detail2 = 0; + if (source) + Accessibility_Registry_notifyEvent (registry, e, &ev); + return TRUE; +} + +static gboolean +bridge_signal_listener (GSignalInvocationHint *signal_hint, + guint n_param_values, + const GValue *param_values, + gpointer data) +{ + Accessibility_Event *e = g_new0(Accessibility_Event, 1); + AtkObject *aobject; + Bonobo_Unknown source; + 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 (property) signal %s:%s\n", + g_type_name (signal_query.itype), name); +#endif + gobject = g_value_get_object (param_values + 0); + + /* notify the actual listeners */ + if (ATK_IS_IMPLEMENTOR (gobject)) + { + aobject = atk_implementor_ref_accessible (ATK_IMPLEMENTOR (gobject)); + } + else if (ATK_IS_OBJECT (gobject)) + { + aobject = ATK_OBJECT (gobject); + g_object_ref (aobject); + } + else + { + g_error("received property-change event from non-AtkImplementor"); + } + + snprintf(sbuf, APP_STATIC_BUFF_SZ, "%s:%s", name, g_type_name (signal_query.itype)); + source = CORBA_Object_duplicate (BONOBO_OBJREF (accessible_new (aobject)), &ev); + e->type = CORBA_string_dup (sbuf); + e->source = source; e->detail1 = 0; e->detail2 = 0; Accessibility_Registry_notifyEvent (registry, e, &ev); - /* CORBA_free (e); */ + g_object_unref (aobject); + return TRUE; } static Accessibility_Registry bridge_get_registry () diff --git a/cspi/spi-impl.h b/cspi/spi-impl.h index 6f8959f..9d34617 100644 --- a/cspi/spi-impl.h +++ b/cspi/spi-impl.h @@ -10,6 +10,7 @@ #ifndef _SPI_IMPL_H_ #define _SPI_IMPL_H_ +#include #include #include "Accessibility.h" diff --git a/cspi/spi-util.c b/cspi/spi-util.c index 6cccb40..2c89479 100644 --- a/cspi/spi-util.c +++ b/cspi/spi-util.c @@ -4,3 +4,32 @@ spi_freeString (char *s) CORBA_free (s); } +boolean +spi_warn_ev (CORBA_Environment *c_ev, char *error_string) { + + if (c_ev->_major != CORBA_NO_EXCEPTION) { + fprintf (stderr, + "Warning: AT-SPI error: %s: %s\n", + error_string, + CORBA_exception_id(c_ev)); + CORBA_exception_init (c_ev); + return FALSE; + } + else + { + return TRUE; + } +} + +void +spi_check_ev (CORBA_Environment *c_ev, char *error_string) { + + if (c_ev->_major != CORBA_NO_EXCEPTION) { + fprintf (stderr, + ("AT-SPI error: %s: %s\n"), + error_string, + CORBA_exception_id(c_ev)); + CORBA_exception_free(c_ev); + exit(-1); + } +} diff --git a/cspi/spi.c b/cspi/spi.c index e895f90..2fe8f87 100644 --- a/cspi/spi.c +++ b/cspi/spi.c @@ -9,8 +9,12 @@ static Accessible * Obj_Add (Accessible object) { /* TODO: keep list of live object refs */ - Accessible *oref = g_malloc (sizeof (Accessible)); - *oref = object; + Accessible *oref = NULL; + if (!CORBA_Object_is_nil (object, &ev)) + { + oref = g_malloc (sizeof (Accessible)); + *oref = object; + } return oref; } diff --git a/cspi/spi.h b/cspi/spi.h index 19d1fa3..49a773b 100644 --- a/cspi/spi.h +++ b/cspi/spi.h @@ -1029,7 +1029,7 @@ long AccessibleSelection_getNSelectedChildren (AccessibleSelection *obj); Accessible * -AccessibleSelection_refSelectedChild (AccessibleSelection *obj, +AccessibleSelection_getSelectedChild (AccessibleSelection *obj, long selectedChildIndex); boolean diff --git a/cspi/spi_accessible.c b/cspi/spi_accessible.c index 6707224..f418ba1 100644 --- a/cspi/spi_accessible.c +++ b/cspi/spi_accessible.c @@ -96,6 +96,7 @@ int Accessible_ref (Accessible *obj) { Accessibility_Accessible_ref (*obj, &ev); + spi_check_ev (&ev, "ref"); return 0; } @@ -113,6 +114,7 @@ int Accessible_unref (Accessible *obj) { Accessibility_Accessible_unref (*obj, &ev); + spi_check_ev (&ev, "unref"); return 0; } @@ -128,8 +130,11 @@ Accessible_unref (Accessible *obj) char * Accessible_getName (Accessible *obj) { - return (char *) + char *retval = + (char *) Accessibility_Accessible__get_name (*obj, &ev); + spi_check_ev (&ev, "getName"); + return retval; } /** @@ -144,8 +149,10 @@ Accessible_getName (Accessible *obj) char * Accessible_getDescription (Accessible *obj) { - return (char *) + char *retval = (char *) Accessibility_Accessible__get_description (*obj, &ev); + spi_check_ev (&ev, "getDescription"); + return retval; } /** @@ -154,14 +161,17 @@ Accessible_getDescription (Accessible *obj) * * Get an #Accessible object's parent container. * - * Returns: a pointer to the #Accessible object which contains the given + * Returns: a pointer tothe #Accessible object which contains the given * #Accessible instance, or NULL if the @obj has no parent container. * **/ Accessible * Accessible_getParent (Accessible *obj) { - return Obj_Add (Accessibility_Accessible__get_parent (*obj, &ev)); + Accessible *retval = + Obj_Add (Accessibility_Accessible__get_parent (*obj, &ev)); + spi_check_ev (&ev, "getParent"); + return retval; } /** @@ -178,7 +188,9 @@ Accessible_getParent (Accessible *obj) long Accessible_getChildCount (Accessible *obj) { - return Accessibility_Accessible__get_childCount (*obj, &ev); + long retval = (long) Accessibility_Accessible__get_childCount (*obj, &ev); + spi_check_ev (&ev, "getChildCount"); + return retval; } /** @@ -197,7 +209,9 @@ Accessible * Accessible_getChildAtIndex (Accessible *obj, long childIndex) { - return Obj_Add (Accessibility_Accessible_getChildAtIndex (*obj, childIndex, &ev)); + Accessible *retval = Obj_Add (Accessibility_Accessible_getChildAtIndex (*obj, childIndex, &ev)); + spi_check_ev (&ev, "getChildAtIndex"); + return retval; } /** @@ -215,7 +229,9 @@ Accessible_getChildAtIndex (Accessible *obj, long Accessible_getIndexInParent (Accessible *obj) { - return Accessibility_Accessible_getIndexInParent (*obj, &ev); + long retval = (long) Accessibility_Accessible_getIndexInParent (*obj, &ev); + spi_check_ev (&ev, "getIndexInParent"); + return retval; } /** @@ -244,8 +260,10 @@ Accessible_getRelationSet (Accessible *obj) char * Accessible_getRole (Accessible *obj) { - return Accessible_Role_getName ( + char *retval = Accessible_Role_getName ( Accessibility_Accessible_getRole (*obj, &ev)); + spi_check_ev (&ev, "getRole"); + return retval; } /** @@ -280,7 +298,9 @@ Accessible_isAction (Accessible *obj) Accessibility_Accessible_queryInterface (*obj, "IDL:Accessibility/Action:1.0", &ev); - return (iface != NULL) ? TRUE : FALSE; + spi_warn_ev (&ev, "isAction"); + + return (CORBA_Object_is_nil (iface, &ev)) ? FALSE : TRUE; } /** @@ -299,7 +319,9 @@ Accessible_isComponent (Accessible *obj) Accessibility_Accessible_queryInterface (*obj, "IDL:Accessibility/Component:1.0", &ev); - return (iface != NULL) ? TRUE : FALSE; + spi_warn_ev (&ev, "isComponent"); + + return (CORBA_Object_is_nil (iface, &ev)) ? FALSE : TRUE; } /** @@ -319,7 +341,9 @@ Accessible_isEditableText (Accessible *obj) Accessibility_Accessible_queryInterface (*obj, "IDL:Accessibility/EditableText:1.0", &ev); - return (iface != NULL) ? TRUE : FALSE; + spi_check_ev (&ev, "isEditableText"); + + return (CORBA_Object_is_nil (iface, &ev)) ? FALSE : TRUE; } /** @@ -339,7 +363,10 @@ Accessible_isHypertext (Accessible *obj) Accessibility_Accessible_queryInterface (*obj, "IDL:Accessibility/Hypertext:1.0", &ev); - return (iface != NULL) ? TRUE : FALSE; + + spi_check_ev (&ev, "isHypertext"); + + return (CORBA_Object_is_nil (iface, &ev)) ? FALSE : TRUE; } /** @@ -359,7 +386,9 @@ Accessible_isImage (Accessible *obj) Accessibility_Accessible_queryInterface (*obj, "IDL:Accessibility/Image:1.0", &ev); - return (iface != NULL) ? TRUE : FALSE; + spi_check_ev (&ev, "isImage"); + + return (CORBA_Object_is_nil (iface, &ev)) ? FALSE : TRUE; } /** @@ -379,7 +408,10 @@ Accessible_isSelection (Accessible *obj) Accessibility_Accessible_queryInterface (*obj, "IDL:Accessibility/Selection:1.0", &ev); - return (iface != NULL) ? TRUE : FALSE; + spi_warn_ev (&ev, "isSelection"); + + return (CORBA_Object_is_nil (iface, &ev)) ? FALSE : TRUE; + } /** @@ -399,7 +431,10 @@ Accessible_isTable (Accessible *obj) Accessibility_Accessible_queryInterface (*obj, "IDL:Accessibility/Table:1.0", &ev); - return (iface != NULL) ? TRUE : FALSE; + spi_check_ev (&ev, "isTable"); + + return (CORBA_Object_is_nil (iface, &ev)) ? FALSE : TRUE; + } /** @@ -419,7 +454,31 @@ Accessible_isText (Accessible *obj) Accessibility_Accessible_queryInterface (*obj, "IDL:Accessibility/Text:1.0", &ev); - return (iface != NULL) ? TRUE : FALSE; + spi_warn_ev (&ev, "isText"); + + return (CORBA_Object_is_nil (iface, &ev)) ? FALSE : TRUE; +} + +/** + * Accessible_isValue: + * @obj: a pointer to the #Accessible instance to query. + * + * Query whether the specified #Accessible implements #AccessibleValue. + * Not Yet Implemented. + * + * Returns: #TRUE if @obj implements the #AccessibleValue interface, + * #FALSE otherwise. +**/ +boolean +Accessible_isValue (Accessible *obj) +{ + Bonobo_Unknown iface = + Accessibility_Accessible_queryInterface (*obj, + "IDL:Accessibility/Value:1.0", + &ev); + spi_check_ev (&ev, "isValue"); + + return (CORBA_Object_is_nil (iface, &ev)) ? FALSE : TRUE; } /** @@ -431,11 +490,14 @@ Accessible_isText (Accessible *obj) AccessibleAction * Accessible_getAction (Accessible *obj) { - AccessibleComponent iface = + Bonobo_Unknown iface = Accessibility_Accessible_queryInterface (*obj, "IDL:Accessibility/Action:1.0", &ev); - return Obj_Add (iface); + spi_check_ev (&ev, "getAction"); + + return (AccessibleAction *) + ((CORBA_Object_is_nil (iface, &ev)) ? 0 : Obj_Add (iface)); } /** @@ -450,21 +512,26 @@ Accessible_getAction (Accessible *obj) AccessibleComponent * Accessible_getComponent (Accessible *obj) { - AccessibleComponent iface = + Bonobo_Unknown iface = Accessibility_Accessible_queryInterface (*obj, "IDL:Accessibility/Component:1.0", &ev); - return Obj_Add (iface); + spi_check_ev (&ev, "getComponent"); + + return (AccessibleComponent *) ((CORBA_Object_is_nil (iface, &ev)) ? 0 : Obj_Add (iface)); } AccessibleEditableText * Accessible_getEditableText (Accessible *obj) { - AccessibleComponent iface = + Bonobo_Unknown iface = Accessibility_Accessible_queryInterface (*obj, "IDL:Accessibility/EditableText:1.0", &ev); - return Obj_Add (iface); + spi_check_ev (&ev, "getEditableText"); + + return (AccessibleEditableText *) + ((CORBA_Object_is_nil (iface, &ev)) ? 0 : Obj_Add (iface)); } @@ -472,11 +539,14 @@ Accessible_getEditableText (Accessible *obj) AccessibleHypertext * Accessible_getHypertext (Accessible *obj) { - AccessibleComponent iface = + Bonobo_Unknown iface = Accessibility_Accessible_queryInterface (*obj, "IDL:Accessibility/Hypertext:1.0", &ev); - return Obj_Add (iface); + spi_check_ev (&ev, "getHypertext"); + + return (AccessibleHypertext *) + ((CORBA_Object_is_nil (iface, &ev)) ? 0 : Obj_Add (iface)); } @@ -484,11 +554,14 @@ Accessible_getHypertext (Accessible *obj) AccessibleImage * Accessible_getImage (Accessible *obj) { - AccessibleImage iface = + Bonobo_Unknown iface = Accessibility_Accessible_queryInterface (*obj, "IDL:Accessibility/Image:1.0", &ev); - return Obj_Add (iface); + spi_check_ev (&ev, "getImage"); + + return (AccessibleImage *) + ((CORBA_Object_is_nil (iface, &ev)) ? 0 : Obj_Add (iface)); } @@ -496,11 +569,14 @@ Accessible_getImage (Accessible *obj) AccessibleSelection * Accessible_getSelection (Accessible *obj) { - AccessibleSelection iface = + Bonobo_Unknown iface = Accessibility_Accessible_queryInterface (*obj, "IDL:Accessibility/Selection:1.0", &ev); - return Obj_Add (iface); + spi_warn_ev (&ev, "getSelection"); + + return (AccessibleSelection *) + ((CORBA_Object_is_nil (iface, &ev)) ? 0 : Obj_Add (iface)); } @@ -508,23 +584,28 @@ Accessible_getSelection (Accessible *obj) AccessibleTable * Accessible_getTable (Accessible *obj) { - AccessibleTable iface = + Bonobo_Unknown iface = Accessibility_Accessible_queryInterface (*obj, "IDL:Accessibility/Table:1.0", &ev); - return Obj_Add (iface); -} - + spi_check_ev (&ev, "getTable"); + return (AccessibleTable *) + ((CORBA_Object_is_nil (iface, &ev)) ? 0 : Obj_Add (iface)); +} AccessibleText * Accessible_getText (Accessible *obj) { - AccessibleText iface = + Bonobo_Unknown iface = Accessibility_Accessible_queryInterface (*obj, "IDL:Accessibility/Text:1.0", &ev); - return Obj_Add (iface); + + spi_check_ev (&ev, "getText"); + + return (AccessibleText *) + ((CORBA_Object_is_nil (iface, &ev)) ? 0 : Obj_Add (iface)); } @@ -532,11 +613,12 @@ Accessible_getText (Accessible *obj) AccessibleValue * Accessible_getValue (Accessible *obj) { - AccessibleComponent iface = + Bonobo_Unknown iface = Accessibility_Accessible_queryInterface (*obj, "IDL:Accessibility/Value:1.0", &ev); - return Obj_Add (iface); + return (AccessibleValue *) + ((CORBA_Object_is_nil (iface, &ev)) ? 0 : Obj_Add (iface)); } diff --git a/cspi/spi_component.c b/cspi/spi_component.c index c695fc4..247a810 100644 --- a/cspi/spi_component.c +++ b/cspi/spi_component.c @@ -109,14 +109,19 @@ AccessibleComponent_getExtents (AccessibleComponent *obj, long *height, AccessibleCoordType ctype) { - /* TODO: remove assumption that CORBA_long == long in typecast */ + CORBA_long cx, cy, cw, ch; Accessibility_Component_getExtents (*obj, - (CORBA_long *) x, - (CORBA_long *) y, - (CORBA_long *) width, - (CORBA_long *) height, - ctype, - &ev); + &cx, + &cy, + &cw, + &ch, + ctype, + &ev); + spi_warn_ev (&ev, "AccessibleComponent_getExtents"); + *x = (long) cx; + *y = (long) cy; + *width = (long) cw; + *height = (long) ch; } /** diff --git a/cspi/spi_selection.c b/cspi/spi_selection.c index fdd12f7..dbef7ef 100644 --- a/cspi/spi_selection.c +++ b/cspi/spi_selection.c @@ -29,12 +29,13 @@ Accessible * AccessibleSelection_getSelectedChild (AccessibleSelection *obj, long selectedChildIndex) { - return (Accessible *) + Accessibility_Accessible child = Accessibility_Selection_getSelectedChild (*obj, (CORBA_long) selectedChildIndex, &ev); -} - + spi_warn_ev (&ev, "getSelectedChild"); + return (Accessible *) ((CORBA_Object_is_nil (child, &ev)) ? NULL : Obj_Add (child)); +} boolean AccessibleSelection_selectChild (AccessibleSelection *obj, diff --git a/cspi/spi_table.c b/cspi/spi_table.c index cf96701..91d9f76 100644 --- a/cspi/spi_table.c +++ b/cspi/spi_table.c @@ -184,7 +184,7 @@ AccessibleTable_getSelectedRows (AccessibleTable *obj, i = rows->_buffer; length = (long) rows->_length; - j = *selectedRows = malloc (sizeof(long)*length); + j = *selectedRows = (long *) malloc (sizeof(long)*length); while (length--) *j++ = (CORBA_long) (*i++); @@ -215,7 +215,7 @@ AccessibleTable_getSelectedColumns (AccessibleTable *obj, i = columns->_buffer; length = (long) columns->_length; - j = *selectedColumns = malloc (sizeof(long)*length); + j = *selectedColumns = (long *) malloc (sizeof(long)*length); while (length--) *j++ = (CORBA_long) (*i++); diff --git a/cspi/spi_text.c b/cspi/spi_text.c index 28bd5bd..4c9ed87 100644 --- a/cspi/spi_text.c +++ b/cspi/spi_text.c @@ -19,8 +19,15 @@ AccessibleText_unref (AccessibleText *obj) long AccessibleText_getCharacterCount (AccessibleText *obj) { - return (long) + long retval; + + CORBA_exception_init (&ev); + retval = (long) Accessibility_Text__get_characterCount (*obj, &ev); + + spi_check_ev (&ev, "AccessibleText_getCharacterCount"); + + return retval; } @@ -101,9 +108,9 @@ AccessibleText_getTextBeforeOffset (AccessibleText *obj, char * AccessibleText_getTextAtOffset (AccessibleText *obj, - long offset, - TEXT_BOUNDARY_TYPE type, - long *startOffset, long *endOffset) + long offset, + TEXT_BOUNDARY_TYPE type, + long *startOffset, long *endOffset) { CORBA_long corbaStartOffset; CORBA_long corbaEndOffset; diff --git a/idl/Accessibility_Application.idl b/idl/Accessibility_Application.idl index 05139bc..01deff3 100644 --- a/idl/Accessibility_Application.idl +++ b/idl/Accessibility_Application.idl @@ -51,12 +51,19 @@ module Accessibility { attribute long id; /** - * Register with this application's toolkit for "toolkit" event notifications. + * Register with this application's toolkit for "toolkit-specific" event notifications. * **/ void registerToolkitEventListener (in EventListener listener, in string eventName); /** + * Register with this application's toolkit for "Accessibility::Accessible" + * event notifications. + * + **/ + void registerObjectEventListener (in EventListener listener, in string eventName); + + /** * pause: * Returns: %true if the request succeeded, %false otherwise. * diff --git a/idl/Application.idl b/idl/Application.idl index 05139bc..01deff3 100644 --- a/idl/Application.idl +++ b/idl/Application.idl @@ -51,12 +51,19 @@ module Accessibility { attribute long id; /** - * Register with this application's toolkit for "toolkit" event notifications. + * Register with this application's toolkit for "toolkit-specific" event notifications. * **/ void registerToolkitEventListener (in EventListener listener, in string eventName); /** + * Register with this application's toolkit for "Accessibility::Accessible" + * event notifications. + * + **/ + void registerObjectEventListener (in EventListener listener, in string eventName); + + /** * pause: * Returns: %true if the request succeeded, %false otherwise. * diff --git a/libspi/accessible.c b/libspi/accessible.c index 3777145..ad5a89f 100644 --- a/libspi/accessible.c +++ b/libspi/accessible.c @@ -67,7 +67,8 @@ accessible_object_finalize (GObject *object) Accessible *accessible = ACCESSIBLE (object); printf("accessible_object_finalize called\n"); - g_object_unref (accessible->atko); + ATK_OBJECT (accessible->atko); /* assertion */ + g_object_unref (G_OBJECT(accessible->atko)); accessible->atko = NULL; printf("atko freed, calling parent finalize\n"); @@ -88,7 +89,7 @@ impl_accessibility_accessible_get_name (PortableServer_Servant servant, retval = CORBA_string_dup (retval); else retval = CORBA_string_dup (""); - fprintf (stderr, "Accessible get_name called: %s\n", retval); + return retval; } @@ -115,7 +116,7 @@ impl_accessibility_accessible_get_description (PortableServer_Servant servant, CORBA_char * retval; Accessible *accessible = ACCESSIBLE (bonobo_object_from_servant (servant)); retval = CORBA_string_dup (atk_object_get_description (accessible->atko)); - fprintf (stderr, "Accessible get_description called: %s\n", retval); + return retval; } @@ -143,9 +144,9 @@ impl_accessibility_accessible_get_parent (PortableServer_Servant servant, Accessible *accessible = ACCESSIBLE (bonobo_object_from_servant (servant)); AtkObject *parent; parent = atk_object_get_parent (accessible->atko); - retval = bonobo_object_corba_objref (bonobo_object (accessible_new (parent))); + retval = BONOBO_OBJREF (accessible_new (parent)); printf ("Accessible get_parent called\n"); - return retval; + return CORBA_Object_duplicate (retval, &ev); } /* @@ -187,9 +188,9 @@ impl_accessibility_accessible_get_child_at_index (PortableServer_Servant servant Accessibility_Accessible retval; Accessible *accessible = ACCESSIBLE (bonobo_object_from_servant (servant)); AtkObject *child = atk_object_ref_accessible_child (accessible->atko, (gint) index); - retval = bonobo_object_corba_objref ( bonobo_object (accessible_new (child))); + retval = BONOBO_OBJREF (accessible_new (child)); printf ("Accessible get_child_at_index called.\n"); - return retval; + return CORBA_Object_duplicate (retval, &ev); } /* @@ -213,7 +214,6 @@ impl_accessibility_accessible_get_state (PortableServer_Servant servant, */ static Accessibility_RelationSet * impl_accessibility_accessible_get_relation_set (PortableServer_Servant servant, - const CORBA_long index, CORBA_Environment *ev) { Accessibility_RelationSet *retval; @@ -233,7 +233,6 @@ impl_accessibility_accessible_get_relation_set (PortableServer_Servant servant, */ static Accessibility_Role impl_accessibility_accessible_get_role (PortableServer_Servant servant, - const CORBA_long index, CORBA_Environment *ev) { Accessibility_Role retval; @@ -313,6 +312,8 @@ accessible_new (AtkObject *o) { Accessible *retval = ACCESSIBLE (g_object_new (accessible_get_type (), NULL)); + CORBA_Environment ev; + CORBA_exception_init (&ev); g_object_ref (o); retval->atko = ATK_OBJECT (o); @@ -328,7 +329,7 @@ accessible_new (AtkObject *o) bonobo_object_add_interface (bonobo_object (retval), BONOBO_OBJECT (action_interface_new (o))); } - + if (ATK_IS_COMPONENT (o)) { bonobo_object_add_interface (bonobo_object (retval), @@ -353,12 +354,6 @@ accessible_new (AtkObject *o) BONOBO_OBJECT (text_interface_new (o))); } - if (ATK_IS_HYPERLINK (o)) - { - bonobo_object_add_interface (bonobo_object (retval), - BONOBO_OBJECT (hyperlink_interface_new(o))); - } - if (ATK_IS_IMAGE (o)) { bonobo_object_add_interface (bonobo_object (retval), @@ -383,6 +378,5 @@ accessible_new (AtkObject *o) BONOBO_OBJECT (value_interface_new (o))); } - return retval; } diff --git a/libspi/accessibleeventlistener.c b/libspi/accessibleeventlistener.c index 2a3bc4f..9de4519 100644 --- a/libspi/accessibleeventlistener.c +++ b/libspi/accessibleeventlistener.c @@ -85,7 +85,7 @@ impl_accessible_event_notify_event (PortableServer_Servant servant, (*cb) (e); } } - Accessibility_Accessible_unref (e->source, ev); + /* Accessibility_Accessible_unref (e->source, ev); */ } static void diff --git a/libspi/action.h b/libspi/action.h index 50a8d10..8b4f013 100644 --- a/libspi/action.h +++ b/libspi/action.h @@ -32,7 +32,7 @@ extern "C" { #define ACTION_TYPE (action_get_type ()) #define ACTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), ACTION_TYPE, Action)) #define ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), ACTION_TYPE, ActionClass)) -#define IS_ACTION(obj) (G_TYPE_CHECK__INSTANCE_TYPE ((obj), ACTION_TYPE)) +#define IS_ACTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), ACTION_TYPE)) #define IS_ACTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), ACTION_TYPE)) typedef struct _Action Action; diff --git a/libspi/application.c b/libspi/application.c index 8c31dd7..9d9d93c 100644 --- a/libspi/application.c +++ b/libspi/application.c @@ -24,6 +24,7 @@ * application.c: implements Application.idl * */ +#include #include #include #include @@ -48,7 +49,17 @@ */ static AccessibleClass *application_parent_class; -Accessibility_EventListener the_toolkit_listener; +static Application *the_app; + +/* static methods */ + +static void notify_listeners (GList *listeners, + Accessibility_Event *e, + CORBA_Environment *ev); + +static char* lookup_toolkit_event_for_name (char *generic_name); + +static char* reverse_lookup_name_for_toolkit_event (char *toolkit_name); /* * Implemented GObject::finalize @@ -57,12 +68,7 @@ static void accessible_application_finalize (GObject *object) { /* TODO: any necessary cleanup */ - Accessible *accessible = ACCESSIBLE (object); - - g_object_unref (accessible->atko); - accessible->atko = NULL; - - /* TODO: chain to parent class instead */ + (G_OBJECT_CLASS (application_parent_class))->finalize (object); } static CORBA_string @@ -107,14 +113,81 @@ impl_accessibility_application_set_id (PortableServer_Servant servant, #define APP_STATIC_BUFF_SZ 64 static gboolean -application_toolkit_listener (GSignalInvocationHint *signal_hint, - guint n_param_values, - const GValue *param_values, - gpointer data) +application_object_event_listener (GSignalInvocationHint *signal_hint, + guint n_param_values, + const GValue *param_values, + gpointer data) +{ + Accessibility_Event *e = Accessibility_Event__alloc(); + AtkObject *aobject; + GObject *gobject; + Accessible *source; + CORBA_Environment ev; + GSignalQuery signal_query; + gchar *name; + char sbuf[APP_STATIC_BUFF_SZ]; + char *generic_name; + + g_signal_query (signal_hint->signal_id, &signal_query); + name = signal_query.signal_name; + fprintf (stderr, "Received (object) signal %s:%s\n", + g_type_name (signal_query.itype), name); + + /* TODO: move GTK dependency out of app.c into bridge */ + snprintf(sbuf, APP_STATIC_BUFF_SZ, "Gtk:%s:%s", g_type_name (signal_query.itype), name); + + generic_name = reverse_lookup_name_for_toolkit_event (sbuf); + gobject = g_value_get_object (param_values + 0); + + /* notify the actual listeners */ + if (ATK_IS_IMPLEMENTOR (gobject)) + { + aobject = atk_implementor_ref_accessible (ATK_IMPLEMENTOR (gobject)); + } + else if (ATK_IS_OBJECT (gobject)) + { + aobject = ATK_OBJECT (gobject); + g_object_ref (G_OBJECT (aobject)); + } + else + { + g_error("received event from non-AtkImplementor"); + } + + g_return_val_if_fail (generic_name, FALSE); + if (generic_name) + { + source = accessible_new (aobject); + e->type = CORBA_string_dup (generic_name); + e->source = BONOBO_OBJREF (source); + /* + * no need to dup this ref, since it's inprocess + * and will be dup'ed by (inprocess) notify_listeners() call below + */ + e->detail1 = 0; + e->detail2 = 0; + if (the_app) notify_listeners (the_app->toolkit_listeners, e, &ev); + /* unref because the in-process notify has called b_o_dup_ref (e->source) */ + bonobo_object_release_unref (e->source, &ev); + } + /* and, decrement the refcount on atkobject, incremented moments ago: + * the call to accessible_new() above should have added an extra ref */ + g_object_unref (G_OBJECT (aobject)); + + return TRUE; +} + + +static gboolean +application_toolkit_event_listener (GSignalInvocationHint *signal_hint, + guint n_param_values, + const GValue *param_values, + gpointer data) { - Accessibility_Event *e = g_new0(Accessibility_Event, 1); + Accessibility_Event *e = Accessibility_Event__alloc(); AtkObject *aobject; GObject *gobject; + Accessible *source; CORBA_Environment ev; GSignalQuery signal_query; gchar *name; @@ -127,32 +200,34 @@ application_toolkit_listener (GSignalInvocationHint *signal_hint, /* TODO: move GTK dependency out of app.c into bridge */ snprintf(sbuf, APP_STATIC_BUFF_SZ, "Gtk:%s:%s", g_type_name (signal_query.itype), name); - gobject = g_value_get_object (param_values + 0); /* notify the actual listeners */ if (ATK_IS_IMPLEMENTOR (gobject)) { aobject = atk_implementor_ref_accessible (ATK_IMPLEMENTOR (gobject)); + source = accessible_new (aobject); e->type = CORBA_string_dup (sbuf); - e->source = bonobo_object_corba_objref (bonobo_object (accessible_new (aobject))); + e->source = BONOBO_OBJREF (source); e->detail1 = 0; e->detail2 = 0; - Accessibility_EventListener_notifyEvent (the_toolkit_listener, e, &ev); - g_object_unref (aobject); + if (the_app) notify_listeners (the_app->toolkit_listeners, e, &ev); + bonobo_object_unref (source); + g_object_unref (G_OBJECT (aobject)); } return TRUE; } static void impl_accessibility_application_register_toolkit_event_listener (PortableServer_Servant servant, - Accessibility_EventListener listener, + Accessibility_EventListener listener, const CORBA_char *event_name, CORBA_Environment *ev) { guint listener_id; listener_id = - atk_add_global_event_listener (application_toolkit_listener, event_name); - the_toolkit_listener = CORBA_Object_duplicate (listener, ev); + atk_add_global_event_listener (application_toolkit_event_listener, event_name); + the_app->toolkit_listeners = g_list_append (the_app->toolkit_listeners, + CORBA_Object_duplicate (listener, ev)); #ifdef SPI_DEBUG fprintf (stderr, "registered %d for toolkit events named: %s\n", listener_id, @@ -161,6 +236,96 @@ impl_accessibility_application_register_toolkit_event_listener (PortableServer_S } static void +impl_accessibility_application_register_object_event_listener (PortableServer_Servant servant, + Accessibility_EventListener listener, + const CORBA_char *event_name, + CORBA_Environment *ev) +{ + guint listener_id; + char *toolkit_specific_event_name = lookup_toolkit_event_for_name (event_name); + if (toolkit_specific_event_name) + { + listener_id = + atk_add_global_event_listener (application_object_event_listener, + CORBA_string_dup (toolkit_specific_event_name)); + the_app->toolkit_listeners = g_list_append (the_app->toolkit_listeners, + CORBA_Object_duplicate (listener, ev)); + } +#ifdef SPI_DEBUG + fprintf (stderr, "registered %d for object events named: %s\n", + listener_id, + event_name); +#endif +} + +static void +notify_listeners (GList *listeners, Accessibility_Event *e, CORBA_Environment *ev) +{ + int n_listeners=0; + int i; + if (listeners) n_listeners = g_list_length (listeners); + + for (i=0; isource = bonobo_object_dup_ref (e->source, ev); + listener = (Accessibility_EventListener) g_list_nth_data (listeners, i); + Accessibility_EventListener_notifyEvent (listener, e, ev); + /* + * when this (oneway) call completes, the CORBA refcount and + * Bonobo_Unknown refcount will be decremented by the recipient + */ + } +} + +static char * +lookup_toolkit_event_for_name (char *generic_name) +{ + char *toolkit_specific_name; + ApplicationClass *klass = g_type_class_peek (APPLICATION_TYPE); +#ifdef SPI_DEBUG + fprintf (stderr, "looking for %s in hash table.\n", generic_name); +#endif + toolkit_specific_name = + (char *) g_hash_table_lookup (klass->toolkit_event_names, generic_name); +#ifdef SPI_DEBUG + fprintf (stderr, "generic event %s converted to %s\n", generic_name, toolkit_specific_name); +#endif + return toolkit_specific_name; +} + +static char * +reverse_lookup_name_for_toolkit_event (char *toolkit_specific_name) +{ + char *generic_name; + ApplicationClass *klass = g_type_class_peek (APPLICATION_TYPE); +#ifdef SPI_DEBUG + fprintf (stderr, "(reverse lookup) looking for %s in hash table.\n", toolkit_specific_name); +#endif + generic_name = + (char *) g_hash_table_lookup (klass->generic_event_names, toolkit_specific_name); +#ifdef SPI_DEBUG + fprintf (stderr, "toolkit event %s converted to %s\n", toolkit_specific_name, generic_name); +#endif + return generic_name; +} + +static void +init_toolkit_names (GHashTable **generic_event_names, GHashTable **toolkit_event_names) +{ + *toolkit_event_names = g_hash_table_new (g_str_hash, g_str_equal); + *generic_event_names = g_hash_table_new (g_str_hash, g_str_equal); + g_hash_table_insert (*toolkit_event_names, + "object:property-change", + "Gtk:AtkObject:property-change"); + g_hash_table_insert (*generic_event_names, + "Gtk:AtkObject:property-change", + "object:property-change"); +#ifdef SPI_DEBUG + fprintf (stderr, "inserted selection_changed hash\n"); +#endif +} + +static void application_class_init (ApplicationClass *klass) { GObjectClass * object_class = (GObjectClass *) klass; @@ -175,12 +340,15 @@ application_class_init (ApplicationClass *klass) epv->_get_id = impl_accessibility_application_get_id; epv->_set_id = impl_accessibility_application_set_id; epv->registerToolkitEventListener = impl_accessibility_application_register_toolkit_event_listener; + init_toolkit_names (&klass->generic_event_names, &klass->toolkit_event_names); } static void application_init (Application *application) { ACCESSIBLE (application)->atko = g_object_new (atk_object_get_type(), NULL); + application->toolkit_listeners = (GList *) NULL; + the_app = application; } GType @@ -224,5 +392,6 @@ application_new (AtkObject *app_root) Application *retval = APPLICATION (g_object_new (application_get_type (), NULL)); ACCESSIBLE (retval)->atko = app_root; + g_object_ref (G_OBJECT (app_root)); return retval; } diff --git a/libspi/application.h b/libspi/application.h index 110cdda..5886d95 100644 --- a/libspi/application.h +++ b/libspi/application.h @@ -41,11 +41,14 @@ extern "C" { typedef struct { Accessible parent; long id; + GList *toolkit_listeners; } Application; typedef struct { AccessibleClass parent_class; POA_Accessibility_Application__epv epv; + GHashTable *toolkit_event_names; + GHashTable *generic_event_names; } ApplicationClass; GType application_get_type (void); diff --git a/libspi/component.c b/libspi/component.c index efd22c9..5e679d9 100644 --- a/libspi/component.c +++ b/libspi/component.c @@ -62,7 +62,7 @@ accessibility_component_object_finalize (GObject *object) g_object_unref (component->atko); component->atko = NULL; - printf("atko freed, calling parent finalize\n"); + printf("component atko freed, calling parent finalize\n"); component_parent_class->finalize (object); } @@ -113,7 +113,7 @@ impl_accessibility_component_get_accessible_at_point (PortableServer_Servant ser (gint) x, (gint) y, (AtkCoordType) coord_type); retval = bonobo_object_corba_objref (bonobo_object (accessible_new (child))); - return retval; + return CORBA_Object_duplicate (retval, ev); } /* @@ -253,5 +253,5 @@ component_interface_new (AtkObject *o) COMPONENT (g_object_new (accessibility_component_get_type (), NULL)); retval->atko = o; g_object_ref (o); -return retval; + return retval; } diff --git a/libspi/editabletext.c b/libspi/editabletext.c index b2a1808..17856ae 100644 --- a/libspi/editabletext.c +++ b/libspi/editabletext.c @@ -124,10 +124,15 @@ editable_text_class_init (EditableTextClass *klass) { GObjectClass * object_class = (GObjectClass *) klass; POA_Accessibility_EditableText__epv *epv = &klass->epv; - parent_class = g_type_class_peek_parent (klass); + parent_class = g_type_interface_peek_parent (klass); object_class->finalize = editable_text_finalize; - + +/* */ + fprintf(stderr, "INITIALIZING editabletext class!\n"); + + fprintf (stderr, "EditableText: get-character-count is at %p\n", + ((TEXT_CLASS(klass))->epv._get_characterCount)); /* Initialize epv table */ @@ -148,10 +153,6 @@ editable_text_init (EditableText *editable) static void editable_text_finalize (GObject *obj) { - EditableText *editable = EDITABLE_TEXT(obj); - Text *text = TEXT(obj); - g_object_unref (text->atko); - text->atko = NULL; parent_class->finalize (obj); } @@ -160,9 +161,9 @@ editable_text_interface_new (AtkObject *obj) { EditableText *new_editable = EDITABLE_TEXT(g_object_new (EDITABLE_TEXT_TYPE, NULL)); - TEXT (new_editable)->atko = obj; + (TEXT (new_editable))->atko = obj; g_object_ref (obj); -return new_editable; + return new_editable; } diff --git a/libspi/eventlistener.c b/libspi/eventlistener.c index 2a3bc4f..9de4519 100644 --- a/libspi/eventlistener.c +++ b/libspi/eventlistener.c @@ -85,7 +85,7 @@ impl_accessible_event_notify_event (PortableServer_Servant servant, (*cb) (e); } } - Accessibility_Accessible_unref (e->source, ev); + /* Accessibility_Accessible_unref (e->source, ev); */ } static void diff --git a/libspi/registry.c b/libspi/registry.c index 208cab5..14622fd 100644 --- a/libspi/registry.c +++ b/libspi/registry.c @@ -60,6 +60,8 @@ static ListenerClass *registry_parent_class; typedef enum { ETYPE_FOCUS, + ETYPE_OBJECT, + ETYPE_PROPERTY, ETYPE_WINDOW, ETYPE_TOOLKIT, ETYPE_LAST_DEFINED @@ -122,7 +124,7 @@ impl_accessibility_registry_register_application (PortableServer_Servant servant fprintf (stderr, "registering app %p\n", application); #endif registry->desktop->applications = g_list_append (registry->desktop->applications, - CORBA_Object_duplicate (application, ev)); + bonobo_object_dup_ref (application, ev)); /* TODO: create unique string here (with libuuid call ?) and hash ? */ Accessibility_Application__set_id (application, _get_unique_id(), ev); @@ -157,7 +159,7 @@ register_with_toolkits (Registry *registry_bonobo_object, EventTypeStruct *etype Accessibility_Desktop desktop; Accessibility_Application app; Accessibility_Registry registry; - registry = bonobo_object_corba_objref (bonobo_object (registry_bonobo_object)); + registry = BONOBO_OBJREF (registry_bonobo_object); /* for each app in each desktop, call ...Application_registerToolkitEventListener */ @@ -172,11 +174,11 @@ register_with_toolkits (Registry *registry_bonobo_object, EventTypeStruct *etype app = (Accessibility_Application) Accessibility_Desktop_getChildAtIndex (desktop, j, ev); - /* TODO: should we be ref-ing the registry object before each call ? */ - Accessibility_Application_registerToolkitEventListener (app, - registry, - CORBA_string_dup (etype->event_name), - ev); + Accessibility_Application_registerToolkitEventListener (app, + registry, + CORBA_string_dup (etype->event_name), + + ev); } } } @@ -200,6 +202,10 @@ parse_event_type (EventTypeStruct *etype, char *event_name) { etype->type_cat = ETYPE_FOCUS; } + else if (!g_ascii_strncasecmp (event_name, "object:", 7)) + { + etype->type_cat = ETYPE_OBJECT; + } else if (!g_ascii_strncasecmp (event_name, "window:", 7)) { etype->type_cat = ETYPE_WINDOW; @@ -296,6 +302,7 @@ impl_accessibility_registry_register_global_event_listener ( Registry *registry = REGISTRY (bonobo_object_from_servant (servant)); ListenerStruct *ls = g_malloc (sizeof (ListenerStruct)); EventTypeStruct etype; + gboolean is_toolkit_specific = TRUE; fprintf(stderr, "registering for events of type %s\n", event_name); @@ -307,9 +314,11 @@ impl_accessibility_registry_register_global_event_listener ( switch (etype.type_cat) { case (ETYPE_FOCUS) : + case (ETYPE_OBJECT) : + case (ETYPE_PROPERTY) : ls->listener = CORBA_Object_duplicate (listener, ev); - registry->focus_listeners = - g_list_append (registry->focus_listeners, ls); + registry->object_listeners = + g_list_append (registry->object_listeners, ls); break; case (ETYPE_WINDOW) : /* Support for Window Manager Events is not yet implemented */ @@ -335,7 +344,7 @@ impl_accessibility_registry_deregister_global_event_listener_all ( CORBA_Environment *ev) { Registry *registry = REGISTRY (bonobo_object_from_servant (servant)); - GList *list = g_list_find_custom (registry->focus_listeners, listener, compare_corba_objects); + GList *list = g_list_find_custom (registry->object_listeners, listener, compare_corba_objects); /* * TODO : de-register with toolkit if the last instance of a listener @@ -345,8 +354,8 @@ impl_accessibility_registry_deregister_global_event_listener_all ( while (list) { fprintf (stderr, "deregistering listener\n"); - registry->focus_listeners = g_list_delete_link (registry->focus_listeners, list); - list = g_list_find_custom (registry->focus_listeners, listener, compare_corba_objects); + registry->object_listeners = g_list_delete_link (registry->object_listeners, list); + list = g_list_find_custom (registry->object_listeners, listener, compare_corba_objects); } list = g_list_find_custom (registry->toolkit_listeners, listener, compare_corba_objects); while (list) @@ -376,8 +385,10 @@ impl_accessibility_registry_deregister_global_event_listener ( parse_event_type (&etype, event_name); switch (etype.type_cat) { + case (ETYPE_OBJECT) : + case (ETYPE_PROPERTY) : case (ETYPE_FOCUS) : - listeners = ®istry->focus_listeners; + listeners = ®istry->object_listeners; break; case (ETYPE_WINDOW) : /* Support for Window Manager Events is not yet implemented */ @@ -438,8 +449,7 @@ impl_accessibility_registry_get_desktop (PortableServer_Servant servant, if (n == 0) { return (Accessibility_Desktop) - CORBA_Object_duplicate ( - bonobo_object_corba_objref (bonobo_object (registry->desktop)), ev); + CORBA_Object_duplicate (BONOBO_OBJREF (registry->desktop), ev); } else { @@ -470,9 +480,7 @@ impl_accessibility_registry_get_device_event_controller (PortableServer_Servant Registry *registry = REGISTRY (bonobo_object_from_servant (servant)); if (!registry->device_event_controller) registry->device_event_controller = g_object_new (DEVICE_EVENT_CONTROLLER_TYPE, NULL); - return CORBA_Object_duplicate ( - bonobo_object_corba_objref ( - bonobo_object (registry->device_event_controller)), ev); + return CORBA_Object_duplicate (BONOBO_OBJREF (registry->device_event_controller), ev); } static void @@ -487,19 +495,21 @@ impl_registry_notify_event (PortableServer_Servant servant, switch (etype.type_cat) { + case (ETYPE_OBJECT) : + case (ETYPE_PROPERTY) : case (ETYPE_FOCUS) : - _registry_notify_listeners (registry->focus_listeners, e, ev); + _registry_notify_listeners (registry->object_listeners, e, ev); break; case (ETYPE_WINDOW) : _registry_notify_listeners (registry->window_listeners, e, ev); break; case (ETYPE_TOOLKIT) : - _registry_notify_listeners (registry->toolkit_listeners, e, ev); + _registry_notify_listeners (registry->toolkit_listeners, e, ev); break; default: break; } - Accessibility_Accessible_unref (e->source, ev); + /* Accessibility_Accessible_unref (e->source, ev);*/ /* This should be here! */ } static long @@ -526,7 +536,7 @@ _registry_notify_listeners ( GList *listeners, for (n=0; nevent_type_hash, etype.hash, minor_hash); fprintf(stderr, "event name: %s\n", etype.event_name); #endif @@ -534,8 +544,9 @@ _registry_notify_listeners ( GList *listeners, { #ifdef SPI_DEBUG fprintf(stderr, "notifying listener #%d\n", n); - fprintf(stderr, "event name %s\n", Accessibility_Accessible__get_name(e->source, ev)); + fprintf(stderr, "event source name %s\n", Accessibility_Accessible__get_name(e->source, ev)); #endif + e->source = CORBA_Object_duplicate (e->source, ev); Accessibility_Accessible_ref ( e->source, ev); Accessibility_EventListener_notifyEvent ((Accessibility_EventListener) ls->listener, e, @@ -585,7 +596,7 @@ registry_class_init (RegistryClass *klass) static void registry_init (Registry *registry) { - registry->focus_listeners = NULL; + registry->object_listeners = NULL; registry->window_listeners = NULL; registry->toolkit_listeners = NULL; registry->applications = NULL; diff --git a/libspi/registry.h b/libspi/registry.h index 7622fe2..ca5a2fe 100644 --- a/libspi/registry.h +++ b/libspi/registry.h @@ -41,7 +41,7 @@ extern "C" { typedef struct { Listener parent; - GList *focus_listeners; + GList *object_listeners; GList *window_listeners; GList *toolkit_listeners; GList *applications; diff --git a/libspi/selection.c b/libspi/selection.c index f80af59..bf33ecf 100644 --- a/libspi/selection.c +++ b/libspi/selection.c @@ -33,6 +33,7 @@ * This pulls the CORBA definitions for the "Accessibility::Accessible" server */ #include +#include "accessible.h" /* * This pulls the definition of the selection bonobo object @@ -165,12 +166,17 @@ static CORBA_long impl__get_nSelectedChildren (PortableServer_Servant _servant, CORBA_Environment * ev) { - Selection *selection = SELECTION (bonobo_object_from_servant (_servant)); + BonoboObject *obj = bonobo_object_from_servant (_servant); + Selection *selection; +#ifdef SPI_DEBUG + fprintf (stderr, "calling impl__get_nSelectedChildren\n"); +#endif + g_return_val_if_fail (IS_SELECTION (obj), 0); + selection = SELECTION (obj); + g_return_val_if_fail (ATK_IS_SELECTION (selection->atko), 0); return (CORBA_long) atk_selection_get_selection_count (ATK_SELECTION(selection->atko)); -} - - +} static Accessibility_Accessible @@ -178,13 +184,27 @@ impl_getSelectedChild (PortableServer_Servant _servant, const CORBA_long selectedChildIndex, CORBA_Environment * ev) { - Selection *selection = SELECTION (bonobo_object_from_servant (_servant)); + BonoboObject *obj = bonobo_object_from_servant (_servant); + Selection + *selection; AtkObject *atk_object; Accessibility_Accessible rv; - - atk_object = atk_selection_ref_selection (ATK_SELECTION(selection->atko), (gint) selectedChildIndex); - rv = bonobo_object_corba_objref (BONOBO_OBJECT(accessible_new(atk_object))); - return rv; +#ifdef SPI_DEBUG + fprintf (stderr, "calling impl_getSelectedChild\n"); +#endif + g_return_val_if_fail (IS_SELECTION (obj), 0); + selection = SELECTION (obj); + g_return_val_if_fail (ATK_IS_SELECTION (selection->atko), 0); + + atk_object = atk_selection_ref_selection (ATK_SELECTION (selection->atko), + (gint) selectedChildIndex); + g_return_val_if_fail (ATK_IS_OBJECT (atk_object), NULL); +#ifdef SPI_DEBUG + fprintf (stderr, "child type is %s\n", g_type_name (G_OBJECT_TYPE (atk_object))); +#endif + rv = bonobo_object_corba_objref (bonobo_object (accessible_new (atk_object))); + g_object_unref (atk_object); + return CORBA_Object_duplicate (rv, ev); } diff --git a/libspi/selection.h b/libspi/selection.h index 02c2882..97cb807 100644 --- a/libspi/selection.h +++ b/libspi/selection.h @@ -32,7 +32,7 @@ extern "C" { #define SELECTION_TYPE (selection_get_type ()) #define SELECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SELECTION_TYPE, Selection)) #define SELECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SELECTION_TYPE, SelectionClass)) -#define IS_SELECTION(obj) (G_TYPE_CHECK__INSTANCE_TYPE ((obj), SELECTION_TYPE)) +#define IS_SELECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), SELECTION_TYPE)) #define IS_SELECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SELECTION_TYPE)) typedef struct _Selection Selection; diff --git a/libspi/table.c b/libspi/table.c index 593522e..17172a9 100644 --- a/libspi/table.c +++ b/libspi/table.c @@ -235,7 +235,7 @@ impl__get_caption (PortableServer_Servant _servant, atk_object = atk_table_get_caption (ATK_TABLE(table-> atko)); rv = bonobo_object_corba_objref (BONOBO_OBJECT(accessible_new(atk_object))); - return rv; + return CORBA_Object_duplicate (rv, ev); } @@ -250,7 +250,7 @@ impl__get_summary (PortableServer_Servant _servant, atk_object = atk_table_get_summary (ATK_TABLE(table->atko)); rv = bonobo_object_corba_objref (BONOBO_OBJECT(accessible_new(atk_object))); - return rv; + return CORBA_Object_duplicate (rv, ev); } @@ -290,7 +290,7 @@ impl_getAccessibleAt (PortableServer_Servant _servant, atk_object = atk_table_ref_at (ATK_TABLE(table->atko), (gint) row, (gint) column); rv = bonobo_object_corba_objref (BONOBO_OBJECT(accessible_new(atk_object))); - return rv; + return CORBA_Object_duplicate (rv, ev); } @@ -405,7 +405,7 @@ impl_getRowHeader (PortableServer_Servant _servant, header = atk_table_get_row_header (ATK_TABLE(table->atko), (gint) row); rv = bonobo_object_corba_objref (BONOBO_OBJECT(accessible_new(header))); - return rv; + return CORBA_Object_duplicate (rv, ev); } @@ -421,7 +421,7 @@ impl_getColumnHeader (PortableServer_Servant _servant, header = atk_table_get_column_header (ATK_TABLE(table->atko), (gint) column); rv = bonobo_object_corba_objref (BONOBO_OBJECT(accessible_new(header))); - return rv; + return CORBA_Object_duplicate (rv, ev); } diff --git a/libspi/text.c b/libspi/text.c index 7b369a7..f7302fc 100644 --- a/libspi/text.c +++ b/libspi/text.c @@ -41,21 +41,36 @@ #include "text.h" /* + * Our parent Gtk object type + */ +#define PARENT_TYPE BONOBO_OBJECT_TYPE + + +/* + * A pointer to our parent object class + */ +static GObjectClass *text_parent_class; + +/* * Static function declarations */ static void -text_class_init (TextClass *klass); +accessibility_text_class_init (TextClass *klass); + static void -text_init (Text *text); +accessibility_text_init (Text *text); + static void -text_finalize (GObject *obj); +accessibility_text_object_finalize (GObject *obj); + static CORBA_string impl_getText (PortableServer_Servant _servant, const CORBA_long startOffset, const CORBA_long endOffset, CORBA_Environment * ev); -CORBA_string + +static CORBA_string impl_getTextAfterOffset (PortableServer_Servant _servant, const CORBA_long offset, const @@ -75,6 +90,7 @@ static CORBA_unsigned_long impl_getCharacterAtOffset (PortableServer_Servant _servant, const CORBA_long offset, CORBA_Environment * ev); + static CORBA_string impl_getTextBeforeOffset (PortableServer_Servant _servant, const CORBA_long offset, @@ -83,15 +99,18 @@ impl_getTextBeforeOffset (PortableServer_Servant _servant, type, CORBA_long * startOffset, CORBA_long * endOffset, CORBA_Environment * ev); + static CORBA_long impl__get_caretOffset (PortableServer_Servant _servant, CORBA_Environment * ev); + static CORBA_string impl_getAttributes (PortableServer_Servant _servant, const CORBA_long offset, CORBA_long * startOffset, CORBA_long * endOffset, CORBA_Environment * ev); + static void impl_getCharacterExtents (PortableServer_Servant _servant, const CORBA_long offset, CORBA_long * x, @@ -99,48 +118,52 @@ impl_getCharacterExtents (PortableServer_Servant _servant, CORBA_long * height, const CORBA_short coordType, CORBA_Environment * ev); + static CORBA_long impl__get_characterCount (PortableServer_Servant _servant, CORBA_Environment * ev); + static CORBA_long impl_getOffsetAtPoint (PortableServer_Servant _servant, const CORBA_long x, const CORBA_long y, const CORBA_short coordType, CORBA_Environment * ev); + static CORBA_long impl_getNSelections (PortableServer_Servant _servant, CORBA_Environment * ev); + static void impl_getSelection (PortableServer_Servant _servant, const CORBA_long selectionNum, CORBA_long * startOffset, CORBA_long * endOffset, CORBA_Environment * ev); + static CORBA_boolean impl_addSelection (PortableServer_Servant _servant, const CORBA_long startOffset, const CORBA_long endOffset, CORBA_Environment * ev); + static CORBA_boolean impl_removeSelection (PortableServer_Servant _servant, const CORBA_long selectionNum, CORBA_Environment * ev); + static CORBA_boolean impl_setSelection (PortableServer_Servant _servant, const CORBA_long selectionNum, const CORBA_long startOffset, const CORBA_long endOffset, CORBA_Environment * ev); + static CORBA_boolean impl_setCaretOffset (PortableServer_Servant _servant, const CORBA_long value, - CORBA_Environment * ev); - - - -static GObjectClass *parent_class; + CORBA_Environment * ev); GType -text_get_type (void) +accessibility_text_get_type (void) { static GType type = 0; @@ -149,13 +172,13 @@ text_get_type (void) sizeof (TextClass), (GBaseInitFunc) NULL, (GBaseFinalizeFunc) NULL, - (GClassInitFunc) text_class_init, + (GClassInitFunc) accessibility_text_class_init, (GClassFinalizeFunc) NULL, NULL, /* class data */ sizeof (Text), 0, /* n preallocs */ - (GInstanceInitFunc) text_init, - NULL /* value table */ + (GInstanceInitFunc) accessibility_text_init, + NULL /* value table */ }; /* @@ -164,7 +187,7 @@ text_get_type (void) * use bonobo_type_unique. */ type = bonobo_type_unique ( - BONOBO_OBJECT_TYPE, + PARENT_TYPE, POA_Accessibility_Text__init, NULL, G_STRUCT_OFFSET (TextClass, epv), @@ -176,14 +199,13 @@ text_get_type (void) } static void -text_class_init (TextClass *klass) +accessibility_text_class_init (TextClass *klass) { GObjectClass * object_class = (GObjectClass *) klass; POA_Accessibility_Text__epv *epv = &klass->epv; - parent_class = g_type_class_peek_parent (klass); - - object_class->finalize = text_finalize; + text_parent_class = g_type_class_peek_parent (klass); + object_class->finalize = accessibility_text_object_finalize; /* Initialize epv table */ @@ -206,24 +228,24 @@ text_class_init (TextClass *klass) } static void -text_init (Text *text) +accessibility_text_init (Text *text) { } static void -text_finalize (GObject *obj) +accessibility_text_object_finalize (GObject *obj) { Text *text = TEXT (obj); g_object_unref (text->atko); text->atko = NULL; - parent_class->finalize (obj); + text_parent_class->finalize (obj); } Text * text_interface_new (AtkObject *obj) { Text *new_text = - TEXT(g_object_new (TEXT_TYPE, NULL)); + TEXT (g_object_new (accessibility_text_get_type (), NULL)); new_text->atko = obj; g_object_ref (obj); return new_text; @@ -239,7 +261,7 @@ impl_getText (PortableServer_Servant _servant, { Text *text; gchar *txt; - CORBA_char *rv; + CORBA_string rv; BonoboObject *obj; obj = (bonobo_object_from_servant (_servant)); @@ -456,13 +478,16 @@ impl__get_characterCount (PortableServer_Servant _servant, { Text *text; BonoboObject *obj; + CORBA_long retval; obj = (bonobo_object_from_servant (_servant)); g_return_val_if_fail (IS_TEXT (obj), (CORBA_long)0); text = TEXT (obj); - return (CORBA_long) + retval = (CORBA_long) atk_text_get_character_count (ATK_TEXT(text->atko)); + + return retval; } diff --git a/libspi/text.h b/libspi/text.h index 53f4817..4c79eec 100644 --- a/libspi/text.h +++ b/libspi/text.h @@ -30,7 +30,7 @@ extern "C" { #include #include "accessible.h" -#define TEXT_TYPE (text_get_type ()) +#define TEXT_TYPE (accessibility_text_get_type ()) #define TEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), TEXT_TYPE, Text)) #define TEXT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), TEXT_TYPE, TextClass)) #define IS_TEXT(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), TEXT_TYPE)) @@ -50,7 +50,7 @@ struct _TextClass { }; GType -text_get_type (void); +accessibility_text_get_type (void); Text * text_interface_new (AtkObject *obj); diff --git a/registryd/registry.c b/registryd/registry.c index 208cab5..14622fd 100644 --- a/registryd/registry.c +++ b/registryd/registry.c @@ -60,6 +60,8 @@ static ListenerClass *registry_parent_class; typedef enum { ETYPE_FOCUS, + ETYPE_OBJECT, + ETYPE_PROPERTY, ETYPE_WINDOW, ETYPE_TOOLKIT, ETYPE_LAST_DEFINED @@ -122,7 +124,7 @@ impl_accessibility_registry_register_application (PortableServer_Servant servant fprintf (stderr, "registering app %p\n", application); #endif registry->desktop->applications = g_list_append (registry->desktop->applications, - CORBA_Object_duplicate (application, ev)); + bonobo_object_dup_ref (application, ev)); /* TODO: create unique string here (with libuuid call ?) and hash ? */ Accessibility_Application__set_id (application, _get_unique_id(), ev); @@ -157,7 +159,7 @@ register_with_toolkits (Registry *registry_bonobo_object, EventTypeStruct *etype Accessibility_Desktop desktop; Accessibility_Application app; Accessibility_Registry registry; - registry = bonobo_object_corba_objref (bonobo_object (registry_bonobo_object)); + registry = BONOBO_OBJREF (registry_bonobo_object); /* for each app in each desktop, call ...Application_registerToolkitEventListener */ @@ -172,11 +174,11 @@ register_with_toolkits (Registry *registry_bonobo_object, EventTypeStruct *etype app = (Accessibility_Application) Accessibility_Desktop_getChildAtIndex (desktop, j, ev); - /* TODO: should we be ref-ing the registry object before each call ? */ - Accessibility_Application_registerToolkitEventListener (app, - registry, - CORBA_string_dup (etype->event_name), - ev); + Accessibility_Application_registerToolkitEventListener (app, + registry, + CORBA_string_dup (etype->event_name), + + ev); } } } @@ -200,6 +202,10 @@ parse_event_type (EventTypeStruct *etype, char *event_name) { etype->type_cat = ETYPE_FOCUS; } + else if (!g_ascii_strncasecmp (event_name, "object:", 7)) + { + etype->type_cat = ETYPE_OBJECT; + } else if (!g_ascii_strncasecmp (event_name, "window:", 7)) { etype->type_cat = ETYPE_WINDOW; @@ -296,6 +302,7 @@ impl_accessibility_registry_register_global_event_listener ( Registry *registry = REGISTRY (bonobo_object_from_servant (servant)); ListenerStruct *ls = g_malloc (sizeof (ListenerStruct)); EventTypeStruct etype; + gboolean is_toolkit_specific = TRUE; fprintf(stderr, "registering for events of type %s\n", event_name); @@ -307,9 +314,11 @@ impl_accessibility_registry_register_global_event_listener ( switch (etype.type_cat) { case (ETYPE_FOCUS) : + case (ETYPE_OBJECT) : + case (ETYPE_PROPERTY) : ls->listener = CORBA_Object_duplicate (listener, ev); - registry->focus_listeners = - g_list_append (registry->focus_listeners, ls); + registry->object_listeners = + g_list_append (registry->object_listeners, ls); break; case (ETYPE_WINDOW) : /* Support for Window Manager Events is not yet implemented */ @@ -335,7 +344,7 @@ impl_accessibility_registry_deregister_global_event_listener_all ( CORBA_Environment *ev) { Registry *registry = REGISTRY (bonobo_object_from_servant (servant)); - GList *list = g_list_find_custom (registry->focus_listeners, listener, compare_corba_objects); + GList *list = g_list_find_custom (registry->object_listeners, listener, compare_corba_objects); /* * TODO : de-register with toolkit if the last instance of a listener @@ -345,8 +354,8 @@ impl_accessibility_registry_deregister_global_event_listener_all ( while (list) { fprintf (stderr, "deregistering listener\n"); - registry->focus_listeners = g_list_delete_link (registry->focus_listeners, list); - list = g_list_find_custom (registry->focus_listeners, listener, compare_corba_objects); + registry->object_listeners = g_list_delete_link (registry->object_listeners, list); + list = g_list_find_custom (registry->object_listeners, listener, compare_corba_objects); } list = g_list_find_custom (registry->toolkit_listeners, listener, compare_corba_objects); while (list) @@ -376,8 +385,10 @@ impl_accessibility_registry_deregister_global_event_listener ( parse_event_type (&etype, event_name); switch (etype.type_cat) { + case (ETYPE_OBJECT) : + case (ETYPE_PROPERTY) : case (ETYPE_FOCUS) : - listeners = ®istry->focus_listeners; + listeners = ®istry->object_listeners; break; case (ETYPE_WINDOW) : /* Support for Window Manager Events is not yet implemented */ @@ -438,8 +449,7 @@ impl_accessibility_registry_get_desktop (PortableServer_Servant servant, if (n == 0) { return (Accessibility_Desktop) - CORBA_Object_duplicate ( - bonobo_object_corba_objref (bonobo_object (registry->desktop)), ev); + CORBA_Object_duplicate (BONOBO_OBJREF (registry->desktop), ev); } else { @@ -470,9 +480,7 @@ impl_accessibility_registry_get_device_event_controller (PortableServer_Servant Registry *registry = REGISTRY (bonobo_object_from_servant (servant)); if (!registry->device_event_controller) registry->device_event_controller = g_object_new (DEVICE_EVENT_CONTROLLER_TYPE, NULL); - return CORBA_Object_duplicate ( - bonobo_object_corba_objref ( - bonobo_object (registry->device_event_controller)), ev); + return CORBA_Object_duplicate (BONOBO_OBJREF (registry->device_event_controller), ev); } static void @@ -487,19 +495,21 @@ impl_registry_notify_event (PortableServer_Servant servant, switch (etype.type_cat) { + case (ETYPE_OBJECT) : + case (ETYPE_PROPERTY) : case (ETYPE_FOCUS) : - _registry_notify_listeners (registry->focus_listeners, e, ev); + _registry_notify_listeners (registry->object_listeners, e, ev); break; case (ETYPE_WINDOW) : _registry_notify_listeners (registry->window_listeners, e, ev); break; case (ETYPE_TOOLKIT) : - _registry_notify_listeners (registry->toolkit_listeners, e, ev); + _registry_notify_listeners (registry->toolkit_listeners, e, ev); break; default: break; } - Accessibility_Accessible_unref (e->source, ev); + /* Accessibility_Accessible_unref (e->source, ev);*/ /* This should be here! */ } static long @@ -526,7 +536,7 @@ _registry_notify_listeners ( GList *listeners, for (n=0; nevent_type_hash, etype.hash, minor_hash); fprintf(stderr, "event name: %s\n", etype.event_name); #endif @@ -534,8 +544,9 @@ _registry_notify_listeners ( GList *listeners, { #ifdef SPI_DEBUG fprintf(stderr, "notifying listener #%d\n", n); - fprintf(stderr, "event name %s\n", Accessibility_Accessible__get_name(e->source, ev)); + fprintf(stderr, "event source name %s\n", Accessibility_Accessible__get_name(e->source, ev)); #endif + e->source = CORBA_Object_duplicate (e->source, ev); Accessibility_Accessible_ref ( e->source, ev); Accessibility_EventListener_notifyEvent ((Accessibility_EventListener) ls->listener, e, @@ -585,7 +596,7 @@ registry_class_init (RegistryClass *klass) static void registry_init (Registry *registry) { - registry->focus_listeners = NULL; + registry->object_listeners = NULL; registry->window_listeners = NULL; registry->toolkit_listeners = NULL; registry->applications = NULL; diff --git a/registryd/registry.h b/registryd/registry.h index 7622fe2..ca5a2fe 100644 --- a/registryd/registry.h +++ b/registryd/registry.h @@ -41,7 +41,7 @@ extern "C" { typedef struct { Listener parent; - GList *focus_listeners; + GList *object_listeners; GList *window_listeners; GList *toolkit_listeners; GList *applications; diff --git a/test/at.c b/test/at.c index 5a57be6..b4a555e 100644 --- a/test/at.c +++ b/test/at.c @@ -101,7 +101,6 @@ main(int argc, char **argv) check_ev (&ev, "register:button_press"); fprintf (stderr, "AT callback registered.\n"); - n_desktops = Accessibility_Registry_getDesktopCount (registry, &ev); for (i=0; itype, - Accessible_getName (&ev->source)); - if (use_festival) { if (festival_chatty) { - _festival_say (Accessible_getRole (&ev->source), "voice_don_diphone", TRUE); + _festival_say (Accessible_getRole (obj), "voice_don_diphone", shutup_previous_speech); } - _festival_say (Accessible_getName (&ev->source), "voice_kal_diphone", festival_chatty==FALSE); + fprintf (stderr, "getting Name\n"); + _festival_say (Accessible_getName (obj), "voice_kal_diphone", + shutup_previous_speech || festival_chatty); } - if (Accessible_isComponent (&ev->source)) + if (Accessible_isComponent (obj)) { long x, y, width, height; - AccessibleComponent *component = Accessible_getComponent (&ev->source); + AccessibleComponent *component = Accessible_getComponent (obj); AccessibleComponent_getExtents (component, &x, &y, &width, &height, COORD_TYPE_SCREEN); fprintf (stderr, "Bounding box: (%ld, %ld) ; (%ld, %ld)\n", @@ -133,20 +134,31 @@ report_focus_event (void *p) magnifier_set_roi (x, y, width, height); } } - if (Accessible_isText(&ev->source)) - /* if this is a text object, speak the first sentence. */ + /* if this is a text object, speak the first sentence. */ + if (Accessible_isText(obj)) { - AccessibleText *text_interface = Accessible_getText (&ev->source); + AccessibleText *text_interface; long start_offset, end_offset; - char *first_sentence = ""; + char *first_sentence = "empty"; + text_interface = Accessible_getText (obj); + fprintf (stderr, "isText...%p %p\n", text_interface, (void *)*text_interface); first_sentence = AccessibleText_getTextAtOffset ( - text_interface, (long) 0, TEXT_BOUNDARY_WORD_END, - &start_offset, &end_offset); - _festival_say(first_sentence, "voice_don_diphone", festival_chatty==FALSE); + text_interface, (long) 0, TEXT_BOUNDARY_SENTENCE_START, &start_offset, &end_offset); + if (first_sentence) _festival_say(first_sentence, "voice_don_diphone", FALSE); + fprintf (stderr, "done reporting on focussed object\n"); } } void +report_focus_event (void *p) +{ + AccessibleEvent *ev = (AccessibleEvent *) p; + fprintf (stderr, "%s event from %s\n", ev->type, + Accessible_getName (&ev->source)); + report_focussed_accessible (&ev->source, TRUE); +} + +void report_button_press (void *p) { AccessibleEvent *ev = (AccessibleEvent *) p; @@ -154,6 +166,30 @@ report_button_press (void *p) Accessible_getName (&ev->source)); } + +void +check_property_change (void *p) +{ + AccessibleEvent *ev = (AccessibleEvent *) p; + AccessibleSelection *selection = Accessible_getSelection (&ev->source); + int n_selections; + int i; + if (selection) + { + n_selections = (int) AccessibleSelection_getNSelectedChildren (selection); + fprintf (stderr, "(Property) %s event from %s, %d selected children\n", ev->type, + Accessible_getName (&ev->source), n_selections); + /* for now, speak entire selection set */ + for (i=0; i