X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=atk-bridge%2Fbridge.c;h=ec6ddd074913a334afbf3088f7bd2ea24c8b9cd6;hb=cd5ac1cc95dd1dce2f8dc6aa617c9dd0d71a4291;hp=7dccf4ecb11e5e43475cc8ece359d344a1fb7c81;hpb=a94a50050845482ecc016e31866326813057f1ce;p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git diff --git a/atk-bridge/bridge.c b/atk-bridge/bridge.c index 7dccf4e..ec6ddd0 100644 --- a/atk-bridge/bridge.c +++ b/atk-bridge/bridge.c @@ -21,34 +21,47 @@ * Boston, MA 02111-1307, USA. */ +#include "config.h" +#include "dbus/dbus-glib.h" + +#include +#include #include #include +#include #include #include -#include -#include #include #include #include -#include -#include #include "accessible.h" -#include "application.h" - -#include #undef SPI_BRIDGE_DEBUG #define DBG(a,b) if(_dbg>=(a))b -static int _dbg = 0; -static CORBA_Environment ev; -static Accessibility_Registry registry = CORBA_OBJECT_NIL; -static Accessibility_DeviceEventController device_event_controller = CORBA_OBJECT_NIL; -static SpiApplication *this_app = NULL; +#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); + +typedef struct _SpiAppData SpiAppData; +struct _SpiAppData +{ + AtkObject *root; + DRouteData droute; +}; + +int _dbg = 0; +static const char *registry = NULL; +static char *device_event_controller = NULL; +static SpiAppData *this_app = NULL; static gboolean registry_died = FALSE; static gboolean atk_listeners_registered = FALSE; -static guint toplevel_handler; +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,27 +78,38 @@ 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 const char *spi_atk_bridge_get_registry (void); +static gboolean spi_atk_bridge_do_registration (void); static void spi_atk_bridge_toplevel_added (AtkObject *object, guint index, AtkObject *child); +static void spi_atk_bridge_toplevel_removed (AtkObject *object, + guint index, + AtkObject *child); 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 void spi_atk_bridge_register_application (Accessibility_Registry registry); +static gchar *spi_atk_bridge_get_registry_ior (void); +static void spi_atk_bridge_register_application (const char *registry); static gboolean spi_atk_bridge_property_event_listener (GSignalInvocationHint *signal_hint, guint n_param_values, const GValue *param_values, gpointer data); + 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, @@ -97,12 +121,15 @@ static gboolean spi_atk_bridge_signal_listener (GSignalInvocationHint *s static gint spi_atk_bridge_key_listener (AtkKeyEventStruct *event, gpointer data); static void spi_atk_tidy_windows (void); +static void deregister_application (); +static void reinit_register_vars (void); /* For automatic libgnome init */ 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; @@ -117,80 +144,160 @@ extern void gnome_accessibility_module_shutdown (void); static void spi_atk_bridge_init_event_type_consts () { + static gboolean done = FALSE; + + if (done) + return; + atk_signal_children_changed = g_signal_lookup ("children_changed", 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", ATK_TYPE_TEXT); + done = TRUE; +} + +static gboolean +post_init (void) +{ + during_init_shutdown = FALSE; + return FALSE; +} + +static DBusObjectPathVTable droute_vtable = +{ + NULL, + &droute_message, + NULL, NULL, NULL, NULL +}; + +static SpiAppData * +spi_app_init (AtkObject *root) +{ + DBusError error; + dbus_error_init(&error); + SpiAppData *ad = (SpiAppData *)calloc(sizeof(SpiAppData), 1); + if (!ad) return NULL; + ad->root = root; + ad->droute.bus = dbus_bus_get(DBUS_BUS_SESSION, &error); + if (!ad->droute.bus) + { + g_warning("Couldn't connect to dbus: %s\n", error.message); + free(ad); + return NULL; + } + //dbus_connection_set_exit_on_disconnect(ad->droute.bus, FALSE); + //dbus_bus_register(ad->droute.bus, &error); + spi_dbus_initialize (&ad->droute); + /* Below line for testing -- it should be removed once at-spi-registryd is working */ + if (dbus_bus_request_name(ad->droute.bus, "test.atspi.tree", 0, &error)) printf("Got test name.\n"); + spi_register_tree_object(ad->droute.bus, "/org/freedesktop/atspi/tree"); + if (!dbus_connection_try_register_fallback (ad->droute.bus, "/org/freedesktop/atspi/accessible/", &droute_vtable, &ad->droute, &error)) + { + g_warning("Couldn't register droute.\n"); + } + dbus_connection_setup_with_g_main(ad->droute.bus, g_main_context_default()); + return ad; } 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 (); - if (debug_env_string) - _dbg = (int) g_ascii_strtod (debug_env_string, NULL); + misc = atk_misc_get_instance(); - if (!bonobo_init (argc, argv ? *argv : NULL)) + if (g_getenv ("ATK_BRIDGE_REDIRECT_LOG")) { - g_error ("Could not initialize Bonobo"); + 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); + + /* Connect to dbus */ + this_app = spi_app_init (atk_get_root ()); + /* * We only want to enable the bridge for top level * applications, we detect bonobo components by seeing * if they were activated with the intention of extracting * an impl. by IID - very solid. */ +#ifdef WITH_BONOBO + // TODO: Figure out if this is still needed if (bonobo_activation_iid_get ()) +#else + if (0) +#endif { DBG (1, g_message ("Found Bonobo component\n")); - toplevel_handler = g_signal_connect (atk_get_root (), - "children-changed::add", - (GCallback) spi_atk_bridge_toplevel_added, - NULL); + g_signal_connect (atk_get_root (), + "children-changed::add", + (GCallback) spi_atk_bridge_toplevel_added, + NULL); + g_signal_connect (atk_get_root (), + "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 () != NULL); } 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 (); + } + else + { + atk_bridge_initialized = FALSE; } - - spi_atk_bridge_init_event_type_consts (); + g_idle_add (post_init, NULL); return 0; } - -static void +static gboolean spi_atk_bridge_do_registration (void) { - CORBA_Environment ev; - - CORBA_exception_init(&ev); - - if (spi_atk_bridge_get_registry () == CORBA_OBJECT_NIL) + if (spi_atk_bridge_get_registry () == NULL) { - 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_app_init (atk_get_root ()); DBG (1, g_message ("About to register application\n")); @@ -199,7 +306,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 @@ -207,73 +314,116 @@ spi_atk_bridge_toplevel_added (AtkObject *object, guint index, AtkObject *child) { - g_signal_handler_disconnect (object, toplevel_handler); - spi_atk_bridge_do_registration (); + if (toplevels == 0) + { + spi_atk_bridge_do_registration (); + } + toplevels++; } static void -spi_atk_bridge_register_application (Accessibility_Registry registry) +spi_atk_bridge_toplevel_removed (AtkObject *object, + guint index, + AtkObject *child) { - Accessibility_Registry_registerApplication (spi_atk_bridge_get_registry (), - BONOBO_OBJREF (this_app), - &ev); - spi_atk_register_event_listeners (); + toplevels--; + if (toplevels == 0) + { + deregister_application (this_app); + reinit_register_vars (); + } + if (toplevels < 0) + { + g_warning ("More toplevels removed than added\n"); + toplevels = 0; + } } -static Accessibility_Registry -spi_atk_bridge_get_registry (void) +static void +spi_atk_bridge_register_application (const char *registry) { - CORBA_Environment ev; + bridge_threads_leave (); + // TODO: register + bridge_threads_enter (); +} - if (registry_died || (registry == NULL)) { - 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); - - if (ev._major != CORBA_NO_EXCEPTION) +/* + * 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) { - g_error ("Accessibility app error: exception during " - "registry activation from id: %s\n", - CORBA_exception_id (&ev)); - CORBA_exception_free (&ev); + 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'; + } + } } - - if (registry_died && registry) { - registry_died = FALSE; - spi_atk_bridge_register_application (registry); + else + { + canonical_display_name = display_env; } - } - return registry; + } + return canonical_display_name; } -static Accessibility_DeviceEventController -spi_atk_bridget_get_dec (void) -{ - CORBA_Environment ev; - - if (device_event_controller != CORBA_OBJECT_NIL) - { - if (ORBit_small_get_connection_status (device_event_controller) - == ORBIT_CONNECTION_CONNECTED) - return device_event_controller; - } +static Display *bridge_display = NULL; - CORBA_exception_init (&ev); +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; + +} - device_event_controller = - Accessibility_Registry_getDeviceEventController ( - spi_atk_bridge_get_registry (), &ev); - if (BONOBO_EX (&ev)) - { - g_warning ("failure: no deviceeventcontroller found\n"); - registry_died = TRUE; - device_event_controller = CORBA_OBJECT_NIL; - } +static const char * +spi_atk_bridge_get_registry (void) +{ + // TODO: check for registry dying, as the old code attempted to do + return "org.freedesktop.atspi.registry"; +} - return device_event_controller; +static const char * +spi_atk_bridget_get_dec (void) +{ + return "/dec"; } int @@ -305,7 +455,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; @@ -339,6 +494,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); @@ -346,6 +510,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"); @@ -372,21 +537,18 @@ spi_atk_register_event_listeners (void) } static void -deregister_application (BonoboObject *app) +deregister_application (SpiAppData *app) { - Accessibility_Registry registry = spi_atk_bridge_get_registry (); - Accessibility_Registry_deregisterApplication (registry, BONOBO_OBJREF (app), &ev); - - device_event_controller = bonobo_object_release_unref (device_event_controller, &ev); - registry = bonobo_object_release_unref (registry, &ev); - - app = bonobo_object_unref (app); + const char *registry = spi_atk_bridge_get_registry (); + bridge_threads_leave (); + // todo: deregister + bridge_threads_enter (); } static void spi_atk_bridge_exit_func (void) { - BonoboObject *app = (BonoboObject *) this_app; + SpiAppData *app = (SpiAppData *) this_app; DBG (1, g_message ("exiting bridge\n")); @@ -394,8 +556,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. */ @@ -405,21 +572,16 @@ spi_atk_bridge_exit_func (void) * shutdown, until we can explicitly shutdown to get the ordering * right. */ - if (!bonobo_is_initialized ()) - { - DBG (1, g_warning ("Re-initializing bonobo\n")); - g_assert (bonobo_init (0, NULL)); - g_assert (bonobo_activate ()); - } - - deregister_application (app); - + if (!registry_died) + deregister_application (this_app); + this_app = NULL; DBG (1, g_message ("bridge exit func complete.\n")); if (g_getenv ("AT_BRIDGE_SHUTDOWN")) { - g_assert (!bonobo_debug_shutdown ()); } + if (bridge_display) + XCloseDisplay (bridge_display); } void @@ -427,13 +589,15 @@ 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 gnome_accessibility_module_shutdown (void) { - BonoboObject *app = (BonoboObject *) this_app; int i; GArray *ids = listener_ids; @@ -441,118 +605,119 @@ 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 (this_app); + this_app = NULL; + + misc = NULL; +} - deregister_application (app); +static void emit(AtkObject *object, const char *name, int first_arg_type, ...) +{ + va_list args; + DBusMessage *sig; + char *path = spi_dbus_get_path(object); + + spi_dbus_update_cache(&this_app->droute); + sig = dbus_message_new_signal(path, "org.freedesktop.atspi.Accessible", name); + va_start(args, first_arg_type); + if (first_arg_type != DBUS_TYPE_INVALID) + { + dbus_message_append_args_valist(sig, first_arg_type, args); + } + va_end(args); + dbus_connection_send(this_app->droute.bus, sig, NULL); + g_free(path); + dbus_message_unref(sig); } static void spi_atk_bridge_focus_tracker (AtkObject *object) { - SpiAccessible *source; - Accessibility_Event e; - - source = spi_accessible_new (object); - - 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); - if (BONOBO_EX (&ev)) - registry_died = TRUE; - - bonobo_object_unref (source); - - CORBA_exception_free (&ev); + emit(object, "focus", DBUS_TYPE_INVALID); } -static void -spi_atk_emit_eventv (const GObject *gobject, - long detail1, - long detail2, - CORBA_any *any, - const char *format, ...) -{ - va_list args; - Accessibility_Event e; - SpiAccessible *source; - AtkObject *aobject; -#ifdef SPI_BRIDGE_DEBUG - CORBA_string s; -#endif - - va_start (args, format); - - if (ATK_IS_IMPLEMENTOR (gobject)) - { - aobject = atk_implementor_ref_accessible (ATK_IMPLEMENTOR (gobject)); - source = spi_accessible_new (aobject); - g_object_unref (G_OBJECT (aobject)); - } - else if (ATK_IS_OBJECT (gobject)) - { - aobject = ATK_OBJECT (gobject); - source = spi_accessible_new (aobject); - } +static void emit_property_change(AtkObject *object, const char *name, int type, void *val) +{ + DBusMessage *sig; + char *path = spi_dbus_get_path(object); + DBusMessageIter iter, sub; + const char *type_as_string = NULL; + + spi_dbus_update_cache(&this_app->droute); + if (type == DBUS_TYPE_OBJECT_PATH) + { + type_as_string = "o"; + if (!val) val = ""; + } + else if (type == DBUS_TYPE_STRING) type_as_string = "s"; + else if (type == DBUS_TYPE_INT32) type_as_string = "i"; + else if (type == DBUS_TYPE_UINT32) type_as_string = "o"; else - { - aobject = NULL; - source = NULL; - DBG (0, g_warning ("received property-change event from non-AtkImplementor")); - } + { + g_warning("Unknown type %d in property change signal", type); + } + sig = dbus_message_new_signal(path, "org.freedesktop.atspi.Accessible", "PropertyChanged"); + dbus_message_iter_init_append(sig, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name); + dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT, type_as_string, &sub); + dbus_message_iter_append_basic(&sub, type, val); + dbus_message_iter_close_container(&iter, &sub); + dbus_connection_send(this_app->droute.bus, sig, NULL); + g_free(path); + dbus_message_unref(sig); +} - if (source) +static void emit_rect(AtkObject *object, const char *name, AtkRectangle *rect) +{ + DBusMessage *sig; + char *path = spi_dbus_get_path(object); + DBusMessageIter iter, sub; + dbus_uint32_t x, y, width, height; + + spi_dbus_update_cache(&this_app->droute); + x = rect->x; + y = rect->y; + width = rect->width; + height = rect->height; + sig = dbus_message_new_signal(path, "org.freedesktop.atspi.Accessible", "PropertyChanged"); + if (sig) { - 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); - -#ifdef SPI_BRIDGE_DEBUG - s = Accessibility_Accessible__get_name (BONOBO_OBJREF (source), &ev); - g_warning ("Emitting event '%s' (%lu, %lu) on %s", - e.type, e.detail1, e.detail2, s); - CORBA_free (s); -#endif - CORBA_exception_init (&ev); - Accessibility_Registry_notifyEvent (spi_atk_bridge_get_registry (), - &e, &ev); -#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)); -#endif - if (BONOBO_EX (&ev)) registry_died = TRUE; - Accessibility_Accessible_unref (e.source, &ev); - - CORBA_exception_free (&ev); - - g_free (e.type); + dbus_message_iter_init_append (sig, &iter); + dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &name); + if (!dbus_message_iter_open_container + (&iter, DBUS_TYPE_STRUCT, NULL, &sub)) + goto oom; + dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &x); + dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &y); + dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &width); + dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &height); + if (!dbus_message_iter_close_container (&iter, &sub)) + goto oom; } - - va_end (args); - + dbus_connection_send(this_app->droute.bus, sig, NULL); +oom: + g_free(path); + dbus_message_unref(sig); } static gboolean @@ -562,130 +727,91 @@ spi_atk_bridge_property_event_listener (GSignalInvocationHint *signal_hint, gpointer data) { AtkPropertyValues *values; - GObject *gobject; + AtkObject *obj; const gchar *prop_name; - CORBA_any any; const gchar *sp = NULL; AtkObject *ao; - SpiAccessible *s_ao = NULL; - CORBA_Object c_obj; + char *s_ao = NULL; 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); + obj = g_value_get_object (param_values + 0); + name = atk_object_get_name (obj); 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_dbus_notify_change(obj, FALSE, &this_app->droute); } else if (strcmp (prop_name, "accessible-description") == 0) { - sp = atk_object_get_description (ATK_OBJECT (gobject)); - spi_init_any_string (&any, (gchar **)&sp); + spi_dbus_notify_change(obj, FALSE, &this_app->droute); } else if (strcmp (prop_name, "accessible-parent") == 0) { - ao = atk_object_get_parent (ATK_OBJECT (gobject)); - if (ao) - { - s_ao = spi_accessible_new (ao); - c_obj = BONOBO_OBJREF (s_ao); - spi_init_any_object (&any, &c_obj); - } - else - { - spi_init_any_nil (&any); - } + spi_dbus_notify_change(obj, FALSE, &this_app->droute); } else if (strcmp (prop_name, "accessible-table-summary") == 0) { - ao = atk_table_get_summary (ATK_TABLE (gobject)); - if (ao) - { - s_ao = spi_accessible_new (ao); - c_obj = BONOBO_OBJREF (s_ao); - spi_init_any_object (&any, &c_obj); - } - else - { - spi_init_any_nil (&any); - } + ao = atk_table_get_summary (ATK_TABLE (obj)); + s_ao = spi_dbus_get_path(ao); + emit_property_change(obj, prop_name, DBUS_TYPE_OBJECT_PATH, s_ao); } else if (strcmp (prop_name, "accessible-table-column-header") == 0) { i = g_value_get_int (&(values->new_value)); - ao = atk_table_get_column_header (ATK_TABLE (gobject), i); - if (ao) - { - s_ao = spi_accessible_new (ao); - c_obj = BONOBO_OBJREF (s_ao); - spi_init_any_object (&any, &c_obj); - } - else - { - spi_init_any_nil (&any); - } + ao = atk_table_get_column_header (ATK_TABLE (obj), i); + s_ao = spi_dbus_get_path(ao); + emit_property_change(obj, prop_name, DBUS_TYPE_OBJECT_PATH, s_ao); } else if (strcmp (prop_name, "accessible-table-row-header") == 0) { i = g_value_get_int (&(values->new_value)); - ao = atk_table_get_row_header (ATK_TABLE (gobject), i); - if (ao) - { - s_ao = spi_accessible_new (ao); - c_obj = BONOBO_OBJREF (s_ao); - spi_init_any_object (&any, &c_obj); - } - else - { - spi_init_any_nil (&any); - } + ao = atk_table_get_row_header (ATK_TABLE (obj), i); + s_ao = spi_dbus_get_path(ao); + emit_property_change(obj, prop_name, DBUS_TYPE_OBJECT_PATH, s_ao); } 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); + sp = atk_table_get_row_description (ATK_TABLE (obj), i); + emit_property_change(obj, prop_name, DBUS_TYPE_STRING, (void *)&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); + sp = atk_table_get_column_description (ATK_TABLE(obj), i); + emit_property_change(obj, prop_name, DBUS_TYPE_STRING, (void *)&sp); } else if (strcmp (prop_name, "accessible-table-caption-object") == 0) { - ao = atk_table_get_caption (ATK_TABLE (gobject)); + ao = atk_table_get_caption (ATK_TABLE(obj)); sp = atk_object_get_name (ao); - spi_init_any_string (&any, (gchar **)&sp); + emit_property_change(obj, prop_name, DBUS_TYPE_STRING, (void *)&sp); } else { - spi_init_any_nil (&any); + long v = 0; + emit_property_change(obj, prop_name, DBUS_TYPE_INT32, &v); } - - spi_atk_emit_eventv (gobject, 0, 0, &any, - "object:property-change:%s", prop_name); - - + if (s_ao) g_free(s_ao); return TRUE; } @@ -695,9 +821,8 @@ spi_atk_bridge_state_event_listener (GSignalInvocationHint *signal_hint, const GValue *param_values, gpointer data) { - GObject *gobject; + AtkObject *obj; gchar *property_name; - gchar *type; unsigned long detail1; #ifdef SPI_BRIDGE_DEBUG GSignalQuery signal_query; @@ -709,21 +834,25 @@ spi_atk_bridge_state_event_listener (GSignalInvocationHint *signal_hint, g_type_name (signal_query.itype), name); #endif - gobject = g_value_get_object (param_values + 0); + obj = ATK_OBJECT(g_value_get_object (param_values + 0)); property_name = g_strdup (g_value_get_string (param_values + 1)); + /* Ignore defunct for now; we'll send a tree update to remove it when + the object goes away */ + /* Also ignore state changes for objects not yet broadcast */ + if ((property_name && !strcmp(property_name, "defunct")) || + !spi_dbus_object_is_known(obj)) + { + g_free(property_name); + return; + } detail1 = (g_value_get_boolean (param_values + 2)) ? 1 : 0; - type = g_strdup_printf ("object:state-changed:%s", property_name); - spi_atk_emit_eventv (gobject, - detail1, - 0, - NULL, - type); + emit(obj, "StateChanged", DBUS_TYPE_STRING, &property_name, DBUS_TYPE_UINT32, &detail1, DBUS_TYPE_INVALID); g_free (property_name); - g_free (type); return TRUE; } +#if 0 static void spi_init_keystroke_from_atk_key_event (Accessibility_DeviceEvent *keystroke, AtkKeyEventStruct *event) @@ -736,8 +865,8 @@ spi_init_keystroke_from_atk_key_event (Accessibility_DeviceEvent *keystroke, else #endif if (!event) - { - g_print ("WARNING: NULL key event!"); + { /* this doesn't really need translating */ + g_print (_("WARNING: NULL key event reported.")); } keystroke->id = (CORBA_long) event->keyval; @@ -779,22 +908,33 @@ spi_init_keystroke_from_atk_key_event (Accessibility_DeviceEvent *keystroke, keystroke->event_string, (int) keystroke->is_text, (unsigned long) keystroke->timestamp); #endif } +#endif static gint spi_atk_bridge_key_listener (AtkKeyEventStruct *event, gpointer data) { - CORBA_boolean result; + gboolean result; +#if 0 Accessibility_DeviceEvent key_event; CORBA_exception_init (&ev); 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); + } + +#endif return result; } @@ -804,17 +944,16 @@ spi_atk_bridge_signal_listener (GSignalInvocationHint *signal_hint, const GValue *param_values, gpointer data) { - GObject *gobject; + AtkObject *obj; GSignalQuery signal_query; const gchar *name; const gchar *detail; - CORBA_any any; - CORBA_Object c_obj; char *sp = NULL; AtkObject *ao; - AtkText *text; gint detail1 = 0, detail2 = 0; - SpiAccessible *s_ao = NULL; + char *s_ao = NULL; + gchar *sig_name; + char *p; #ifdef SPI_BRIDGE_DEBUG const gchar *s, *s2; #endif @@ -823,9 +962,16 @@ spi_atk_bridge_signal_listener (GSignalInvocationHint *signal_hint, name = signal_query.signal_name; if (signal_hint->detail) + { detail = g_quark_to_string (signal_hint->detail); + sig_name = g_strdup_printf("object_%s_%s", name, detail); + } else + { detail = NULL; + sig_name = g_strdup_printf("object_%s", name); + } + while ((p = strchr(sig_name, '-')) != NULL) *p = '_'; #ifdef SPI_BRIDGE_DEBUG s2 = g_type_name (G_OBJECT_TYPE (g_value_get_object (param_values + 0))); @@ -835,7 +981,7 @@ spi_atk_bridge_signal_listener (GSignalInvocationHint *signal_hint, detail ? detail : "", s ? s : "" , s2); #endif - gobject = g_value_get_object (param_values + 0); + obj = ATK_OBJECT(g_value_get_object (param_values + 0)); if (signal_query.signal_id == atk_signal_active_descendant_changed) { @@ -846,31 +992,27 @@ spi_atk_bridge_signal_listener (GSignalInvocationHint *signal_hint, ao = ATK_OBJECT (child); 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); + s_ao = spi_dbus_get_path(child); + emit(obj, "name", DBUS_TYPE_OBJECT_PATH, s_ao, DBUS_TYPE_UINT32, &detail1, DBUS_TYPE_INVALID); + g_free(s_ao); } 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); + emit(obj, "LinkSelected", DBUS_TYPE_UINT32, &detail1, DBUS_TYPE_INVALID); } - else if ((signal_query.signal_id == atk_signal_children_changed) && gobject) + else if (signal_query.signal_id == atk_signal_bounds_changed) { - 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); - g_object_unref (ao); - } - else - { - spi_init_any_nil (&any); - } + AtkRectangle *atk_rect = NULL; + + if (G_VALUE_HOLDS_BOXED (param_values + 1)) + atk_rect = g_value_get_boxed (param_values + 1); + emit_rect(obj, "BoundsChanged", atk_rect); + } + else if ((signal_query.signal_id == atk_signal_children_changed) && obj) + { + spi_dbus_notify_change(obj, FALSE, &this_app->droute); } else { @@ -887,34 +1029,30 @@ spi_atk_bridge_signal_listener (GSignalInvocationHint *signal_hint, if (signal_query.signal_id == atk_signal_text_changed) { - sp = atk_text_get_text (ATK_TEXT (gobject), + sp = atk_text_get_text (ATK_TEXT (obj), detail1, detail1+detail2); - spi_init_any_string (&any, &sp); + emit(obj, sig_name, DBUS_TYPE_UINT32, &detail1, DBUS_TYPE_UINT32, &detail2, DBUS_TYPE_STRING, &sp, DBUS_TYPE_INVALID); } 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); + // TODO + emit(obj, sig_name, DBUS_TYPE_INVALID); } else { - spi_init_any_nil (&any); + emit(obj, sig_name, DBUS_TYPE_INVALID); } } - if (detail) - spi_atk_emit_eventv (gobject, detail1, detail2, &any, - "object:%s:%s", name, detail); - else - spi_atk_emit_eventv (gobject, detail1, detail2, &any, - "object:%s", name); - - if (sp) + if (sp) g_free (sp); + if (s_ao) + g_free (s_ao); + g_free(sig_name); + return TRUE; } @@ -924,9 +1062,8 @@ spi_atk_bridge_window_event_listener (GSignalInvocationHint *signal_hint, const GValue *param_values, gpointer data) { - GObject *gobject; + AtkObject *obj; GSignalQuery signal_query; - CORBA_any any; const gchar *name, *s; #ifdef SPI_BRIDGE_DEBUG const gchar *s2; @@ -935,6 +1072,7 @@ spi_atk_bridge_window_event_listener (GSignalInvocationHint *signal_hint, g_signal_query (signal_hint->signal_id, &signal_query); name = signal_query.signal_name; + gchar *sig_name; #ifdef SPI_BRIDGE_DEBUG s2 = g_type_name (G_OBJECT_TYPE (g_value_get_object (param_values + 0))); @@ -943,13 +1081,47 @@ spi_atk_bridge_window_event_listener (GSignalInvocationHint *signal_hint, g_type_name (signal_query.itype), name, s ? s : "" , s2); #endif - gobject = g_value_get_object (param_values + 0); + obj = ATK_OBJECT(g_value_get_object (param_values + 0)); + + s = atk_object_get_name (obj); + sig_name = g_strdup_printf("window_%s", name); + emit(obj, sig_name, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID); + g_free(sig_name); - s = atk_object_get_name (ATK_OBJECT (gobject)); - spi_init_any_string (&any, (char **) &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) +{ + AtkObject *obj; + GSignalQuery signal_query; + const gchar *name, *s; + gchar *sig_name; +#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 + + obj = ATK_OBJECT(g_value_get_object (param_values + 0)); + + s = atk_object_get_name (obj); + sig_name = g_strdup_printf("document_%s", name); + emit(obj, sig_name, DBUS_TYPE_STRING, &s, DBUS_TYPE_INVALID); + g_free(sig_name); return TRUE; } @@ -966,21 +1138,27 @@ spi_atk_tidy_windows (void) { AtkObject *child; AtkStateSet *stateset; - CORBA_any any; const gchar *name; child = atk_object_ref_accessible_child (root, i); 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_emit_eventv (G_OBJECT (child), 0, 0, &any, "window:deactivate"); + emit(child, "window:deactivate", DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID); } - g_free (stateset); + g_object_unref (stateset); - spi_atk_emit_eventv (G_OBJECT (child), 0, 0, &any, "window:destroy"); + emit(child, "window:destroy", DBUS_TYPE_STRING, &name, DBUS_TYPE_INVALID); g_object_unref (child); } } + +static void +reinit_register_vars (void) +{ + registry = NULL; + device_event_controller = NULL; + this_app = NULL; +}