X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=atk-bridge%2Fbridge.c;h=755310b6928ccd7408cc5ce340d920d979a1ca49;hb=5d01be6ec7d2cb2e662c695bd4c28c50ac3f2dab;hp=4065745f2550d6fd3b57dd999fbc93cb3c01a204;hpb=1885defa72d1861ac2330fa91c81af760d2f4c7c;p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git diff --git a/atk-bridge/bridge.c b/atk-bridge/bridge.c index 4065745..755310b 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-lowlevel.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 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 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); @@ -77,19 +91,25 @@ 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_deregister_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, @@ -101,14 +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 (BonoboObject *app); -static void reinit_register_vars (void); +static void deregister_application (SpiAppData *app); +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; @@ -123,45 +144,113 @@ 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 (gpointer data) +{ + 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")); g_signal_connect (atk_get_root (), @@ -172,35 +261,43 @@ 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 () != NULL); } else { - spi_atk_bridge_do_registration (); + success = spi_atk_bridge_do_registration (); } - - spi_atk_bridge_init_event_type_consts (); + /* + * 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; + } + 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")); @@ -209,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 @@ -218,7 +315,9 @@ spi_atk_bridge_toplevel_added (AtkObject *object, AtkObject *child) { if (toplevels == 0) - spi_atk_bridge_do_registration (); + { + spi_atk_bridge_do_registration (); + } toplevels++; } @@ -227,13 +326,10 @@ spi_atk_bridge_toplevel_removed (AtkObject *object, guint index, AtkObject *child) { - BonoboObject *app = (BonoboObject *) this_app; - toplevels--; if (toplevels == 0) { - deregister_application (app); - spi_atk_deregister_event_listeners (); + deregister_application (this_app); reinit_register_vars (); } if (toplevels < 0) @@ -244,68 +340,90 @@ spi_atk_bridge_toplevel_removed (AtkObject *object, } static void -spi_atk_bridge_register_application (Accessibility_Registry registry) +spi_atk_bridge_register_application (const char *registry) { - Accessibility_Registry_registerApplication (spi_atk_bridge_get_registry (), - BONOBO_OBJREF (this_app), - &ev); - spi_atk_register_event_listeners (); + bridge_threads_leave (); + // TODO: register + bridge_threads_enter (); } -static Accessibility_Registry -spi_atk_bridge_get_registry (void) +/* + * Returns a 'canonicalized' value for DISPLAY, + * with the screen number stripped off if present. + */ +static const gchar* +spi_display_name (void) { - CORBA_Environment ev; - - 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); - - if (ev._major != CORBA_NO_EXCEPTION) + 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; +static Display *bridge_display = NULL; - if (device_event_controller != CORBA_OBJECT_NIL) - { - if (ORBit_small_get_connection_status (device_event_controller) - == ORBIT_CONNECTION_CONNECTED) - return device_event_controller; - } - - 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_bridge_get_dec (void) +{ + return "/dec"; } int @@ -337,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; @@ -371,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); @@ -378,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"); @@ -404,47 +537,18 @@ spi_atk_register_event_listeners (void) } static void -spi_atk_deregister_event_listeners (void) -{ - gint i; - guint id; - - if (!atk_listeners_registered) - return; - - atk_listeners_registered = FALSE; - - for (i = 0; i < listener_ids->len; i++) - { - id = g_array_index (listener_ids, guint, i); - atk_remove_global_event_listener (id); - } - g_array_free (listener_ids, TRUE); - listener_ids = NULL; - - atk_remove_focus_tracker (atk_bridge_focus_tracker_id); - atk_bridge_focus_tracker_id = 0; - - atk_remove_key_event_listener (atk_bridge_key_event_listener_id); - atk_bridge_key_event_listener_id = 0; -} - -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")); @@ -452,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. */ @@ -463,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 @@ -485,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; @@ -499,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 (app); + deregister_application (this_app); + this_app = NULL; + + misc = NULL; +} + +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, ...) +static void emit_property_change(AtkObject *object, const char *name, int type, void *val) { - 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); - } + 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 @@ -620,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; } @@ -753,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; @@ -767,18 +834,21 @@ 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 TRUE; + } 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; } @@ -794,29 +864,29 @@ 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; - keystroke->hw_code = (CORBA_short) event->keycode; - keystroke->timestamp = (CORBA_unsigned_long) event->timestamp; - keystroke->modifiers = (CORBA_unsigned_short) (event->state & 0xFFFF); + keystroke->id = (dbus_int32_t) event->keyval; + keystroke->hw_code = (dbus_int16_t) event->keycode; + keystroke->timestamp = (dbus_uint32_t) event->timestamp; + keystroke->modifiers = (dbus_uint16_t) (event->state & 0xFFFF); if (event->string) { gunichar c; - keystroke->event_string = CORBA_string_dup (event->string); + keystroke->event_string = g_strdup (event->string); c = g_utf8_get_char_validated (event->string, -1); if (c > 0 && g_unichar_isprint (c)) - keystroke->is_text = CORBA_TRUE; + keystroke->is_text = TRUE; else - keystroke->is_text = CORBA_FALSE; + keystroke->is_text = FALSE; } else { - keystroke->event_string = CORBA_string_dup (""); - keystroke->is_text = CORBA_FALSE; + keystroke->event_string = g_strdup (""); + keystroke->is_text = FALSE; } switch (event->type) { @@ -838,20 +908,41 @@ spi_init_keystroke_from_atk_key_event (Accessibility_DeviceEvent *keystroke, #endif } +static gboolean Accessibility_DeviceEventController_notifyListenersSync(const Accessibility_DeviceEvent *key_event) +{ + DBusMessage *message = dbus_message_new_method_call(SPI_DBUS_NAME_REGISTRY, SPI_DBUS_PATH_REGISTRY, "org.freedesktop.atspi.DeviceEventController", "notifyListenersSync"); + DBusError error; + dbus_bool_t consumed = FALSE; + + dbus_error_init(&error); + if (spi_dbus_marshall_deviceEvent(message, key_event)) + { + DBusMessage *reply = dbus_connection_send_with_reply_and_block(this_app->droute.bus, message, 1000, &error); + if (reply) + { + DBusError error; + dbus_error_init(&error); + dbus_message_get_args(reply, &error, DBUS_TYPE_BOOLEAN, &consumed, DBUS_TYPE_INVALID); + dbus_message_unref(reply); + } + } + dbus_message_unref(message); + return consumed; +} + static gint spi_atk_bridge_key_listener (AtkKeyEventStruct *event, gpointer data) { - CORBA_boolean result; + gboolean result; Accessibility_DeviceEvent key_event; - CORBA_exception_init (&ev); - spi_init_keystroke_from_atk_key_event (&key_event, event); - result = Accessibility_DeviceEventController_notifyListenersSync ( - spi_atk_bridget_get_dec (), &key_event, &ev); + bridge_threads_leave (); + result = Accessibility_DeviceEventController_notifyListenersSync (&key_event); + bridge_threads_enter (); - CORBA_exception_free (&ev); + if (key_event.event_string) g_free (key_event.event_string); return result; } @@ -862,17 +953,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 @@ -881,9 +971,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))); @@ -893,7 +990,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) { @@ -904,31 +1001,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 { @@ -945,34 +1038,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; } @@ -982,9 +1071,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; @@ -993,6 +1081,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))); @@ -1001,13 +1090,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; } @@ -1024,21 +1147,19 @@ 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); } } @@ -1046,8 +1167,7 @@ spi_atk_tidy_windows (void) static void reinit_register_vars (void) { - registry = CORBA_OBJECT_NIL; - device_event_controller = CORBA_OBJECT_NIL; + registry = NULL; + device_event_controller = NULL; this_app = NULL; } -