X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=atk-bridge%2Fbridge.c;h=7a3362a691f6d1710eebad5c4e427974767c2bc7;hb=1549eff5b0fda58d3684a4a01953a2c9892f59f5;hp=2adbe989c172e72eb2a4047a4aa430ac3630ce3e;hpb=4a41fd5865acddfcb7c8d0f0860dbc0a092c9268;p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git diff --git a/atk-bridge/bridge.c b/atk-bridge/bridge.c index 2adbe98..7a3362a 100644 --- a/atk-bridge/bridge.c +++ b/atk-bridge/bridge.c @@ -21,8 +21,13 @@ * Boston, MA 02111-1307, USA. */ +#include "config.h" + +#include +#include #include #include +#include #include #include #include @@ -32,16 +37,21 @@ #include #include #include +#include "remoteobject.h" #include "accessible.h" #include "application.h" - #include #undef SPI_BRIDGE_DEBUG #define DBG(a,b) if(_dbg>=(a))b -static int _dbg = 0; +#define bridge_threads_leave() \ + if (!during_init_shutdown && !g_main_context_is_owner (NULL)) atk_misc_threads_leave(misc); +#define bridge_threads_enter() \ + if (!during_init_shutdown && !g_main_context_is_owner (NULL)) atk_misc_threads_enter(misc); + +int _dbg = 0; static CORBA_Environment ev; static Accessibility_Registry registry = CORBA_OBJECT_NIL; static Accessibility_DeviceEventController device_event_controller = CORBA_OBJECT_NIL; @@ -49,6 +59,9 @@ static SpiApplication *this_app = NULL; static gboolean registry_died = FALSE; static gboolean atk_listeners_registered = FALSE; static gint toplevels = 0; +static gboolean exiting = FALSE; +static AtkMisc *misc = NULL; +static gboolean during_init_shutdown = TRUE; static guint atk_signal_text_changed; static guint atk_signal_children_changed; @@ -65,9 +78,10 @@ static guint atk_signal_text_selection_changed; */ static guint atk_signal_link_selected; +static guint atk_signal_bounds_changed; static Accessibility_Registry spi_atk_bridge_get_registry (void); -static void spi_atk_bridge_do_registration (void); +static gboolean spi_atk_bridge_do_registration (void); static void spi_atk_bridge_toplevel_added (AtkObject *object, guint index, AtkObject *child); @@ -78,17 +92,36 @@ static void spi_atk_bridge_toplevel_removed (AtkObject *o static void spi_atk_bridge_exit_func (void); static void spi_atk_register_event_listeners (void); static void spi_atk_bridge_focus_tracker (AtkObject *object); +static gchar *spi_atk_bridge_get_registry_ior (void); static void spi_atk_bridge_register_application (Accessibility_Registry registry); static gboolean spi_atk_bridge_property_event_listener (GSignalInvocationHint *signal_hint, guint n_param_values, const GValue *param_values, gpointer data); + +static void spi_atk_bridge_init_nil (CORBA_any *any, + AtkObject *obj); +static void spi_atk_bridge_init_object (CORBA_any *any, + AtkObject *obj, + CORBA_Object *c_obj); +static void spi_atk_bridge_init_string (CORBA_any *any, + AtkObject *obj, + gchar **string); +static void spi_atk_bridge_init_rect (CORBA_any *any, + AtkObject *obj, + AtkRectangle *rect); + static gboolean spi_atk_bridge_window_event_listener (GSignalInvocationHint *signal_hint, guint n_param_values, const GValue *param_values, gpointer data); static gboolean +spi_atk_bridge_document_event_listener (GSignalInvocationHint *signal_hint, + guint n_param_values, + const GValue *param_values, + gpointer data); +static gboolean spi_atk_bridge_state_event_listener (GSignalInvocationHint *signal_hint, guint n_param_values, const GValue *param_values, @@ -108,6 +141,7 @@ extern void gnome_accessibility_module_init (void); extern void gnome_accessibility_module_shutdown (void); static int atk_bridge_initialized = FALSE; +static pid_t atk_bridge_pid = 0; static guint atk_bridge_focus_tracker_id = 0; static guint atk_bridge_key_event_listener_id = 0; static GArray *listener_ids = NULL; @@ -131,9 +165,11 @@ spi_atk_bridge_init_event_type_consts () ATK_TYPE_OBJECT); atk_signal_text_changed = g_signal_lookup ("text_changed", ATK_TYPE_TEXT); + atk_signal_bounds_changed = g_signal_lookup ("bounds_changed", + ATK_TYPE_COMPONENT); atk_signal_active_descendant_changed = g_signal_lookup ("active_descendant_changed", - ATK_TYPE_OBJECT); + ATK_TYPE_OBJECT); atk_signal_link_selected = g_signal_lookup ("link_selected", ATK_TYPE_HYPERTEXT); atk_signal_text_selection_changed = g_signal_lookup ("text_selection_changed", @@ -141,25 +177,50 @@ spi_atk_bridge_init_event_type_consts () done = TRUE; } +static gboolean +post_init (void) +{ + during_init_shutdown = FALSE; + return FALSE; +} + static int atk_bridge_init (gint *argc, gchar **argv[]) { const char *debug_env_string = g_getenv ("AT_SPI_DEBUG"); + gchar *fname; + gboolean success = FALSE; if (atk_bridge_initialized) { return 0; } atk_bridge_initialized = TRUE; + atk_bridge_pid = getpid (); + + misc = atk_misc_get_instance(); + + if (g_getenv ("ATK_BRIDGE_REDIRECT_LOG")) + { + fname = g_strconcat ("/tmp/", g_get_prgname (), ".at-spi-log", NULL); + /* make sure we're not being redirected - security issue */ + if (!g_file_test (fname, G_FILE_TEST_IS_SYMLINK)) + freopen (fname, "w", stderr); + g_free (fname); + } - if (debug_env_string) - _dbg = (int) g_ascii_strtod (debug_env_string, NULL); + if (debug_env_string) + _dbg = (int) g_ascii_strtod (debug_env_string, NULL); if (!bonobo_init (argc, argv ? *argv : NULL)) { g_error ("Could not initialize Bonobo"); } + bonobo_activate (); + + /* Create the accessible application server object */ + this_app = spi_application_new (atk_get_root ()); /* * We only want to enable the bridge for top level * applications, we detect bonobo components by seeing @@ -177,19 +238,33 @@ atk_bridge_init (gint *argc, gchar **argv[]) "children-changed::remove", (GCallback) spi_atk_bridge_toplevel_removed, NULL); + /* in this case we redefine 'success' to mean 'registry is present' */ + success = (spi_atk_bridge_get_registry () != CORBA_OBJECT_NIL); } else { - spi_atk_bridge_do_registration (); + success = spi_atk_bridge_do_registration (); + } + /* + * we must emit events even if we are not registered as a + * full-fledged app; See bugzilla #400709. + */ + if (success) + { + spi_atk_register_event_listeners (); + spi_atk_bridge_init_event_type_consts (); } - spi_atk_register_event_listeners (); - spi_atk_bridge_init_event_type_consts (); - + else + { + atk_bridge_initialized = FALSE; + } + g_idle_add (post_init, NULL); + return 0; } -static void +static gboolean spi_atk_bridge_do_registration (void) { CORBA_Environment ev; @@ -198,14 +273,13 @@ spi_atk_bridge_do_registration (void) if (spi_atk_bridge_get_registry () == CORBA_OBJECT_NIL) { - g_error ("Could not locate registry"); + g_warning ("Could not locate registry"); + return FALSE; } - bonobo_activate (); - /* Create the accessible application server object */ - - this_app = spi_application_new (atk_get_root ()); + if (this_app == NULL) + this_app = spi_application_new (atk_get_root ()); DBG (1, g_message ("About to register application\n")); @@ -214,7 +288,7 @@ spi_atk_bridge_do_registration (void) g_atexit (spi_atk_bridge_exit_func); DBG (1, g_message ("Application registered & listening\n")); - + return TRUE; } static void @@ -252,36 +326,127 @@ spi_atk_bridge_toplevel_removed (AtkObject *object, static void spi_atk_bridge_register_application (Accessibility_Registry registry) { + bridge_threads_leave (); Accessibility_Registry_registerApplication (spi_atk_bridge_get_registry (), BONOBO_OBJREF (this_app), &ev); + bridge_threads_enter (); + if (ev._major != CORBA_NO_EXCEPTION) + CORBA_exception_free (&ev); } +/* + * Returns a 'canonicalized' value for DISPLAY, + * with the screen number stripped off if present. + */ +static const gchar* +spi_display_name (void) +{ + static const char *canonical_display_name = NULL; + if (!canonical_display_name) + { + const gchar *display_env = g_getenv ("AT_SPI_DISPLAY"); + if (!display_env) + { + display_env = g_getenv ("DISPLAY"); + if (!display_env || !display_env[0]) + canonical_display_name = ":0"; + else + { + gchar *display_p, *screen_p; + canonical_display_name = g_strdup (display_env); + display_p = strrchr (canonical_display_name, ':'); + screen_p = strrchr (canonical_display_name, '.'); + if (screen_p && display_p && (screen_p > display_p)) + { + *screen_p = '\0'; + } + } + } + else + { + canonical_display_name = display_env; + } + } + return canonical_display_name; +} + +static Display *bridge_display = NULL; + +static gchar * +spi_atk_bridge_get_registry_ior (void) +{ + + Atom AT_SPI_IOR; + Atom actual_type; + int actual_format; + unsigned char *data = NULL; + unsigned long nitems; + unsigned long leftover; + if (!bridge_display) + bridge_display = XOpenDisplay (spi_display_name ()); + + AT_SPI_IOR = XInternAtom (bridge_display, "AT_SPI_IOR", False); + XGetWindowProperty(bridge_display, + XDefaultRootWindow (bridge_display), + AT_SPI_IOR, 0L, + (long)BUFSIZ, False, + (Atom) 31, &actual_type, &actual_format, + &nitems, &leftover, &data); + if (data == NULL) + g_warning (_("AT_SPI_REGISTRY was not started at session startup.")); + + return (gchar *) data; + +} + + static Accessibility_Registry spi_atk_bridge_get_registry (void) { CORBA_Environment ev; + char *ior = NULL; + + if (registry_died || (registry == CORBA_OBJECT_NIL)) + { + CORBA_exception_init (&ev); + if (registry_died) + { + if (exiting) + return CORBA_OBJECT_NIL; + else + DBG (1, g_warning ("registry died! restarting...")); + } - if (registry_died || (registry == CORBA_OBJECT_NIL)) { - CORBA_exception_init (&ev); - if (registry_died) - DBG (1, g_warning ("registry died! restarting...")); - registry = bonobo_activation_activate_from_id ( - "OAFIID:Accessibility_Registry:1.0", 0, NULL, &ev); + /* XXX: This presumes that the registry has successfully restarted itself already...*/ + ior = (char *) spi_atk_bridge_get_registry_ior (); + + if (ior != NULL) + { + registry = CORBA_ORB_string_to_object (bonobo_activation_orb_get (), + ior, &ev); + XFree (ior); + } + else + { + g_warning ("IOR not set."); + registry = CORBA_OBJECT_NIL; + } - if (ev._major != CORBA_NO_EXCEPTION) - { - g_error ("Accessibility app error: exception during " - "registry activation from id: %s\n", - CORBA_exception_id (&ev)); - CORBA_exception_free (&ev); - } + if (ev._major != CORBA_NO_EXCEPTION) + { + g_error ("Accessibility app error: exception during " + "registry activation from id: %s\n", + CORBA_exception_id (&ev)); + CORBA_exception_free (&ev); + } - if (registry_died && registry) { - registry_died = FALSE; - spi_atk_bridge_register_application (registry); - } - } + if (registry_died && registry) + { + registry_died = FALSE; + spi_atk_bridge_register_application (registry); + } + } return registry; } @@ -342,7 +507,12 @@ spi_atk_register_event_listeners (void) AtkObject *bo = atk_no_op_object_new (ao); - if (atk_listeners_registered) return; + if (atk_listeners_registered) + { + g_object_unref (G_OBJECT (bo)); + g_object_unref (ao); + return; + } atk_listeners_registered = TRUE; @@ -376,6 +546,15 @@ spi_atk_register_event_listeners (void) id = atk_add_global_event_listener (spi_atk_bridge_window_event_listener, "window:deactivate"); g_array_append_val (listener_ids, id); + id = atk_add_global_event_listener (spi_atk_bridge_document_event_listener, + "Gtk:AtkDocument:load-complete"); + g_array_append_val (listener_ids, id); + id = atk_add_global_event_listener (spi_atk_bridge_document_event_listener, + "Gtk:AtkDocument:reload"); + g_array_append_val (listener_ids, id); + id = atk_add_global_event_listener (spi_atk_bridge_document_event_listener, + "Gtk:AtkDocument:load-stopped"); + g_array_append_val (listener_ids, id); id = atk_add_global_event_listener (spi_atk_bridge_state_event_listener, "Gtk:AtkObject:state-change"); g_array_append_val (listener_ids, id); @@ -383,6 +562,7 @@ spi_atk_register_event_listeners (void) add_signal_listener ("Gtk:AtkObject:children-changed"); add_signal_listener ("Gtk:AtkObject:visible-data-changed"); add_signal_listener ("Gtk:AtkObject:active-descendant-changed"); + add_signal_listener ("Gtk:AtkComponent:bounds-changed"); add_signal_listener ("Gtk:AtkSelection:selection-changed"); add_signal_listener ("Gtk:AtkText:text-selection-changed"); add_signal_listener ("Gtk:AtkText:text-changed"); @@ -411,13 +591,13 @@ spi_atk_register_event_listeners (void) static void deregister_application (BonoboObject *app) { - Accessibility_Registry registry = spi_atk_bridge_get_registry (); + Accessibility_Registry registry = spi_atk_bridge_get_registry (); + bridge_threads_leave (); Accessibility_Registry_deregisterApplication (registry, BONOBO_OBJREF (app), &ev); + bridge_threads_enter (); device_event_controller = bonobo_object_release_unref (device_event_controller, &ev); registry = bonobo_object_release_unref (registry, &ev); - - app = bonobo_object_unref (app); } static void @@ -432,7 +612,13 @@ spi_atk_bridge_exit_func (void) return; } this_app = NULL; + if (atk_bridge_pid != getpid ()) + { + _exit (0); + } + during_init_shutdown = TRUE; + exiting = TRUE; /* * Check whether we still have windows which have not been deleted. */ @@ -449,7 +635,8 @@ spi_atk_bridge_exit_func (void) g_assert (bonobo_activate ()); } - deregister_application (app); + if (!registry_died) + deregister_application (app); DBG (1, g_message ("bridge exit func complete.\n")); @@ -457,6 +644,8 @@ spi_atk_bridge_exit_func (void) { g_assert (!bonobo_debug_shutdown ()); } + if (bridge_display) + XCloseDisplay (bridge_display); } void @@ -464,7 +653,10 @@ gnome_accessibility_module_init (void) { atk_bridge_init (NULL, NULL); - g_print("Atk Accessibilty bridge initialized\n"); + if (g_getenv ("AT_BRIDGE_SHUTDOWN")) + { + g_print("Atk Accessibility bridge initialized\n"); + } } void @@ -478,22 +670,30 @@ gnome_accessibility_module_shutdown (void) { return; } + during_init_shutdown = TRUE; atk_bridge_initialized = FALSE; this_app = NULL; - g_print("Atk Accessibilty bridge shutdown\n"); + if (g_getenv ("AT_BRIDGE_SHUTDOWN")) + { + g_print("Atk Accessibility bridge shutdown\n"); + } listener_ids = NULL; - atk_remove_focus_tracker (atk_bridge_focus_tracker_id); + if (atk_bridge_focus_tracker_id) + atk_remove_focus_tracker (atk_bridge_focus_tracker_id); for (i = 0; ids && i < ids->len; i++) - { + { atk_remove_global_event_listener (g_array_index (ids, guint, i)); - } + } - atk_remove_key_event_listener (atk_bridge_key_event_listener_id); + if (atk_bridge_key_event_listener_id) + atk_remove_key_event_listener (atk_bridge_key_event_listener_id); deregister_application (app); + + misc = NULL; } static void @@ -501,22 +701,33 @@ spi_atk_bridge_focus_tracker (AtkObject *object) { SpiAccessible *source; Accessibility_Event e; - + source = spi_accessible_new (object); - + + CORBA_exception_init (&ev); + e.type = "focus:"; e.source = BONOBO_OBJREF (source); e.detail1 = 0; e.detail2 = 0; - spi_init_any_nil (&e.any_data); - - CORBA_exception_init (&ev); - Accessibility_Registry_notifyEvent (spi_atk_bridge_get_registry (), &e, &ev); + spi_atk_bridge_init_nil (&e.any_data, object); + if (BONOBO_EX (&ev)) + registry_died = TRUE; + else + { + bridge_threads_leave (); + Accessibility_Registry_notifyEvent (spi_atk_bridge_get_registry (), + &e, &ev); + bridge_threads_enter (); + } if (BONOBO_EX (&ev)) registry_died = TRUE; bonobo_object_unref (source); - + + if (e.any_data._release) + CORBA_free (e.any_data._value); + CORBA_exception_free (&ev); } @@ -529,10 +740,11 @@ spi_atk_emit_eventv (const GObject *gobject, { va_list args; Accessibility_Event e; - SpiAccessible *source; AtkObject *aobject; + SpiAccessible *source = NULL; + Accessibility_Registry registry; #ifdef SPI_BRIDGE_DEBUG - CORBA_string s; + CORBA_string s = NULL; #endif va_start (args, format); @@ -546,48 +758,63 @@ spi_atk_emit_eventv (const GObject *gobject, else if (ATK_IS_OBJECT (gobject)) { aobject = ATK_OBJECT (gobject); - source = spi_accessible_new (aobject); + if (SPI_IS_REMOTE_OBJECT (aobject)) + e.source = spi_remote_object_get_accessible (SPI_REMOTE_OBJECT (aobject)); + else + source = spi_accessible_new (aobject); } else { aobject = NULL; - source = NULL; DBG (0, g_warning ("received property-change event from non-AtkImplementor")); + va_end (args); + return; } - - if (source) - { - e.type = g_strdup_vprintf (format, args); - e.source = BONOBO_OBJREF (source); - e.detail1 = detail1; - e.detail2 = detail2; - if (any) e.any_data = *any; - else spi_init_any_nil (&e.any_data); + e.type = g_strdup_vprintf (format, args); + if (source) e.source = BONOBO_OBJREF (source); + e.detail1 = detail1; + e.detail2 = detail2; + if (any) e.any_data = *any; + else spi_atk_bridge_init_nil (&e.any_data, aobject); #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); + if (e.source != CORBA_OBJECT_NIL) + s = Accessibility_Accessible__get_name (e.source, &ev); + g_message ("Emitting event '%s' (%lu, %lu) on %s", + e.type, e.detail1, e.detail2, s); + CORBA_free (s); #endif - CORBA_exception_init (&ev); - Accessibility_Registry_notifyEvent (spi_atk_bridge_get_registry (), - &e, &ev); + CORBA_exception_init (&ev); + registry = spi_atk_bridge_get_registry (); + if (!registry_died) + { + bridge_threads_leave (); + Accessibility_Registry_notifyEvent (registry, + &e, &ev); + bridge_threads_enter (); #ifdef SPI_BRIDGE_DEBUG - if (ev._major != CORBA_NO_EXCEPTION) - g_warning ("error emitting event %s, (%d) %s", - e.type, - ev._major, - CORBA_exception_id(&ev)); + if (ev._major != CORBA_NO_EXCEPTION) + g_message ("error emitting event %s, (%d) %s", + e.type, + ev._major, + CORBA_exception_id(&ev)); #endif - if (BONOBO_EX (&ev)) registry_died = TRUE; - Accessibility_Accessible_unref (e.source, &ev); - - CORBA_exception_free (&ev); - - g_free (e.type); + if (BONOBO_EX (&ev)) registry_died = TRUE; } + if (source) + bonobo_object_unref (BONOBO_OBJECT (source)); + else + Bonobo_Unknown_unref (e.source, &ev); + + CORBA_exception_free (&ev); + + g_free (e.type); + + if (!any && e.any_data._release) CORBA_free (e.any_data._value); + + if (any && any->_release) CORBA_free (any->_value); + va_end (args); } @@ -607,36 +834,41 @@ spi_atk_bridge_property_event_listener (GSignalInvocationHint *signal_hint, SpiAccessible *s_ao = NULL; CORBA_Object c_obj; gint i; + const gchar *name = NULL; #ifdef SPI_BRIDGE_DEBUG GSignalQuery signal_query; - const gchar *name; + const gchar *signame; const gchar *s, *s2; g_signal_query (signal_hint->signal_id, &signal_query); - name = signal_query.signal_name; + signame = signal_query.signal_name; s2 = g_type_name (G_OBJECT_TYPE (g_value_get_object (param_values + 0))); s = atk_object_get_name (ATK_OBJECT (g_value_get_object (param_values + 0))); values = (AtkPropertyValues*) g_value_get_pointer (param_values + 1); DBG (2, g_message ("Received (property) signal %s:%s:%s from object %s (gail %s)\n", - g_type_name (signal_query.itype), name, values->property_name, s, s2)); + g_type_name (signal_query.itype), signame, values->property_name, s, s2)); #endif gobject = g_value_get_object (param_values + 0); + name = atk_object_get_name (ATK_OBJECT (gobject)); values = (AtkPropertyValues*) g_value_get_pointer (param_values + 1); prop_name = values->property_name; if (strcmp (prop_name, "accessible-name") == 0) { - sp = atk_object_get_name (ATK_OBJECT (gobject)); - spi_init_any_string (&any, (gchar **)&sp); + spi_atk_bridge_init_string (&any, + ATK_OBJECT (gobject), + (gchar **)&name); } else if (strcmp (prop_name, "accessible-description") == 0) { sp = atk_object_get_description (ATK_OBJECT (gobject)); - spi_init_any_string (&any, (gchar **)&sp); + spi_atk_bridge_init_string (&any, + ATK_OBJECT (gobject), + (gchar **)&sp); } else if (strcmp (prop_name, "accessible-parent") == 0) { @@ -645,11 +877,14 @@ spi_atk_bridge_property_event_listener (GSignalInvocationHint *signal_hint, { s_ao = spi_accessible_new (ao); c_obj = BONOBO_OBJREF (s_ao); - spi_init_any_object (&any, &c_obj); + spi_atk_bridge_init_object (&any, + ATK_OBJECT (gobject), + &c_obj); } else { - spi_init_any_nil (&any); + spi_atk_bridge_init_nil (&any, + ATK_OBJECT (gobject)); } } else if (strcmp (prop_name, "accessible-table-summary") == 0) @@ -659,11 +894,14 @@ spi_atk_bridge_property_event_listener (GSignalInvocationHint *signal_hint, { s_ao = spi_accessible_new (ao); c_obj = BONOBO_OBJREF (s_ao); - spi_init_any_object (&any, &c_obj); + spi_atk_bridge_init_object (&any, + ATK_OBJECT (gobject), + &c_obj); } else { - spi_init_any_nil (&any); + spi_atk_bridge_init_nil (&any, + ATK_OBJECT (gobject)); } } else if (strcmp (prop_name, "accessible-table-column-header") == 0) @@ -674,11 +912,13 @@ spi_atk_bridge_property_event_listener (GSignalInvocationHint *signal_hint, { s_ao = spi_accessible_new (ao); c_obj = BONOBO_OBJREF (s_ao); - spi_init_any_object (&any, &c_obj); + spi_atk_bridge_init_object (&any, + ATK_OBJECT (gobject), + &c_obj); } else { - spi_init_any_nil (&any); + spi_atk_bridge_init_nil (&any, ATK_OBJECT (gobject)); } } else if (strcmp (prop_name, "accessible-table-row-header") == 0) @@ -689,39 +929,44 @@ spi_atk_bridge_property_event_listener (GSignalInvocationHint *signal_hint, { s_ao = spi_accessible_new (ao); c_obj = BONOBO_OBJREF (s_ao); - spi_init_any_object (&any, &c_obj); + spi_atk_bridge_init_object (&any, ATK_OBJECT (gobject), &c_obj); } else { - spi_init_any_nil (&any); + spi_atk_bridge_init_nil (&any, ATK_OBJECT (gobject)); } } else if (strcmp (prop_name, "accessible-table-row-description") == 0) { i = g_value_get_int (&(values->new_value)); sp = atk_table_get_row_description (ATK_TABLE (gobject), i); - spi_init_any_string (&any, (gchar **)&sp); + spi_atk_bridge_init_string (&any, ATK_OBJECT (gobject), + (gchar **)&sp); } else if (strcmp (prop_name, "accessible-table-column-description") == 0) { i = g_value_get_int (&(values->new_value)); sp = atk_table_get_column_description (ATK_TABLE (gobject), i); - spi_init_any_string (&any, (gchar **)&sp); + spi_atk_bridge_init_string (&any, ATK_OBJECT (gobject), + (gchar **)&sp); } else if (strcmp (prop_name, "accessible-table-caption-object") == 0) { ao = atk_table_get_caption (ATK_TABLE (gobject)); sp = atk_object_get_name (ao); - spi_init_any_string (&any, (gchar **)&sp); + spi_atk_bridge_init_string (&any, ATK_OBJECT (gobject), + (gchar **)&sp); } else { - spi_init_any_nil (&any); + spi_atk_bridge_init_nil (&any, ATK_OBJECT (gobject)); } spi_atk_emit_eventv (gobject, 0, 0, &any, "object:property-change:%s", prop_name); + if (s_ao) + bonobo_object_unref (BONOBO_OBJECT (s_ao)); return TRUE; } @@ -773,7 +1018,7 @@ spi_init_keystroke_from_atk_key_event (Accessibility_DeviceEvent *keystroke, else #endif if (!event) - { + { /* this doesn't really need translating */ g_print (_("WARNING: NULL key event reported.")); } @@ -827,10 +1072,18 @@ spi_atk_bridge_key_listener (AtkKeyEventStruct *event, gpointer data) spi_init_keystroke_from_atk_key_event (&key_event, event); + bridge_threads_leave (); result = Accessibility_DeviceEventController_notifyListenersSync ( spi_atk_bridget_get_dec (), &key_event, &ev); + bridge_threads_enter (); - CORBA_exception_free (&ev); + if (key_event.event_string) CORBA_free (key_event.event_string); + + if (BONOBO_EX(&ev)) + { + result = FALSE; + CORBA_exception_free (&ev); + } return result; } @@ -849,7 +1102,6 @@ spi_atk_bridge_signal_listener (GSignalInvocationHint *signal_hint, CORBA_Object c_obj; char *sp = NULL; AtkObject *ao; - AtkText *text; gint detail1 = 0, detail2 = 0; SpiAccessible *s_ao = NULL; #ifdef SPI_BRIDGE_DEBUG @@ -885,28 +1137,37 @@ spi_atk_bridge_signal_listener (GSignalInvocationHint *signal_hint, detail1 = atk_object_get_index_in_parent (ao); s_ao = spi_accessible_new (ao); c_obj = BONOBO_OBJREF (s_ao); - spi_init_any_object (&any, &c_obj); + spi_atk_bridge_init_object (&any, ATK_OBJECT (gobject), &c_obj); } else if (signal_query.signal_id == atk_signal_link_selected) { if (G_VALUE_TYPE (param_values + 1) == G_TYPE_INT) detail1 = g_value_get_int (param_values + 1); - spi_init_any_nil (&any); + spi_atk_bridge_init_nil (&any, ATK_OBJECT (gobject)); + } + else if (signal_query.signal_id == atk_signal_bounds_changed) + { + AtkRectangle *atk_rect = NULL; + + if (G_VALUE_HOLDS_BOXED (param_values + 1)) + atk_rect = g_value_get_boxed (param_values + 1); + spi_atk_bridge_init_rect (&any, ATK_OBJECT (gobject), atk_rect); } else if ((signal_query.signal_id == atk_signal_children_changed) && gobject) { + detail1 = g_value_get_uint (param_values + 1); ao = atk_object_ref_accessible_child (ATK_OBJECT (gobject), detail1); if (ao) { s_ao = spi_accessible_new (ao); c_obj = BONOBO_OBJREF (s_ao); - spi_init_any_object (&any, &c_obj); + spi_atk_bridge_init_object (&any, ATK_OBJECT (gobject), &c_obj); g_object_unref (ao); } else { - spi_init_any_nil (&any); + spi_atk_bridge_init_nil (&any, ATK_OBJECT (gobject)); } } else @@ -927,18 +1188,17 @@ spi_atk_bridge_signal_listener (GSignalInvocationHint *signal_hint, sp = atk_text_get_text (ATK_TEXT (gobject), detail1, detail1+detail2); - spi_init_any_string (&any, &sp); + spi_atk_bridge_init_string (&any, ATK_OBJECT (gobject), + (gchar **) &sp); } else if (signal_query.signal_id == atk_signal_text_selection_changed) { - text = ATK_TEXT (gobject); - /* Return NULL as the selected string */ - spi_init_any_nil (&any); + spi_atk_bridge_init_nil (&any, ATK_OBJECT (gobject)); } else { - spi_init_any_nil (&any); + spi_atk_bridge_init_nil (&any, ATK_OBJECT (gobject)); } } @@ -949,9 +1209,12 @@ spi_atk_bridge_signal_listener (GSignalInvocationHint *signal_hint, spi_atk_emit_eventv (gobject, detail1, detail2, &any, "object:%s", name); - if (sp) + if (sp) g_free (sp); + if (s_ao) + bonobo_object_unref (BONOBO_OBJECT (s_ao)); + return TRUE; } @@ -983,13 +1246,48 @@ spi_atk_bridge_window_event_listener (GSignalInvocationHint *signal_hint, gobject = g_value_get_object (param_values + 0); s = atk_object_get_name (ATK_OBJECT (gobject)); - spi_init_any_string (&any, (char **) &s); + spi_atk_bridge_init_string (&any, ATK_OBJECT (gobject), (gchar **) &s); spi_atk_emit_eventv (gobject, 0, 0, &any, "window:%s", name); return TRUE; } +static gboolean +spi_atk_bridge_document_event_listener (GSignalInvocationHint *signal_hint, + guint n_param_values, + const GValue *param_values, + gpointer data) +{ + GObject *gobject; + GSignalQuery signal_query; + CORBA_any any; + const gchar *name, *s; +#ifdef SPI_BRIDGE_DEBUG + const gchar *s2; +#endif + + g_signal_query (signal_hint->signal_id, &signal_query); + + name = signal_query.signal_name; + +#ifdef SPI_BRIDGE_DEBUG + s2 = g_type_name (G_OBJECT_TYPE (g_value_get_object (param_values + 0))); + s = atk_object_get_name (ATK_OBJECT (g_value_get_object (param_values + 0))); + 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); + + s = atk_object_get_name (ATK_OBJECT (gobject)); + spi_atk_bridge_init_string (&any, ATK_OBJECT (gobject), (gchar **) &s); + + spi_atk_emit_eventv (gobject, 0, 0, &any, + "document:%s", name); + return TRUE; +} + static void spi_atk_tidy_windows (void) { @@ -1010,13 +1308,16 @@ spi_atk_tidy_windows (void) stateset = atk_object_ref_state_set (child); name = atk_object_get_name (child); - spi_init_any_string (&any, (char**) &name); if (atk_state_set_contains_state (stateset, ATK_STATE_ACTIVE)) { + spi_atk_bridge_init_string (&any, child, (gchar**) &name); spi_atk_emit_eventv (G_OBJECT (child), 0, 0, &any, "window:deactivate"); + if (registry_died) + return; } - g_free (stateset); + g_object_unref (stateset); + spi_atk_bridge_init_string (&any, child, (gchar**) &name); spi_atk_emit_eventv (G_OBJECT (child), 0, 0, &any, "window:destroy"); g_object_unref (child); } @@ -1030,3 +1331,54 @@ reinit_register_vars (void) this_app = NULL; } +static void +spi_atk_bridge_init_base (CORBA_any *any, AtkObject *obj, + Accessibility_Application *app, Accessibility_Role *role, + CORBA_string *name) +{ + const gchar *s = atk_object_get_name (obj); + *app = spi_accessible_new_return (atk_get_root (), FALSE, NULL); + *role = spi_role_from_atk_role (atk_object_get_role (obj)); + *name = s ? s : ""; /* string gets dup-ed in util.c spi_init_any_* */ +} + +static void +spi_atk_bridge_init_nil (CORBA_any *any, AtkObject *obj) +{ + Accessibility_Application app = CORBA_OBJECT_NIL; + Accessibility_Role role = Accessibility_ROLE_UNKNOWN; + CORBA_string name; + spi_atk_bridge_init_base (any, obj, &app, &role, &name); + spi_init_any_nil (any, app, role, name); +} + +static void +spi_atk_bridge_init_object (CORBA_any *any, AtkObject *obj, CORBA_Object *c_obj) +{ + Accessibility_Application app = CORBA_OBJECT_NIL; + Accessibility_Role role = Accessibility_ROLE_UNKNOWN; + CORBA_string name; + spi_atk_bridge_init_base (any, obj, &app, &role, &name); + spi_init_any_object (any, app, role, name, c_obj); +} + +static void +spi_atk_bridge_init_string (CORBA_any *any, AtkObject *obj, gchar **string) +{ + Accessibility_Application app = CORBA_OBJECT_NIL; + Accessibility_Role role = Accessibility_ROLE_UNKNOWN; + CORBA_string name; + spi_atk_bridge_init_base (any, obj, &app, &role, &name); + spi_init_any_string (any, app, role, name, string); +} + +static void +spi_atk_bridge_init_rect (CORBA_any *any, AtkObject *obj, AtkRectangle *rect) +{ + Accessibility_Application app = CORBA_OBJECT_NIL; + Accessibility_Role role = Accessibility_ROLE_UNKNOWN; + CORBA_string name; + spi_atk_bridge_init_base (any, obj, &app, &role, &name); + spi_init_any_rect (any, app, role, name, rect); +} +