X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git;a=blobdiff_plain;f=atk-adaptor%2Fbridge.c;h=cb14c8a6c98696db42d8c0e393f51d90c69e73de;hp=3e5fba4d22dea3b9b0fe18a3b66503cfeaca3b6e;hb=62ef943cbe84b8293bd99910a6a01d432d122eb5;hpb=90b6e52a7695cb9fbb01e1cdcef01f5a544d2651 diff --git a/atk-adaptor/bridge.c b/atk-adaptor/bridge.c index 3e5fba4..cb14c8a 100644 --- a/atk-adaptor/bridge.c +++ b/atk-adaptor/bridge.c @@ -2,7 +2,7 @@ * AT-SPI - Assistive Technology Service Provider Interface * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) * - * Copyright 2008 Codethink Ltd. + * Copyright 2008, 2009 Codethink Ltd. * Copyright 2001, 2002, 2003 Sun Microsystems Inc., * Copyright 2001, 2002, 2003 Ximian, Inc. * @@ -27,25 +27,29 @@ #include #include -#include -#include #include #include +#include #include +#include #include -#include -#include -#include "accessible.h" + +#include + #include "bridge.h" -#include "atk-dbus.h" +#include "event.h" +#include "adaptors.h" +#include "object.h" + +#include "accessible-register.h" +#include "accessible-leasing.h" +#include "accessible-cache.h" -void spi_atk_register_event_listeners (void); -void spi_atk_deregister_event_listeners (void); -void spi_atk_tidy_windows (void); +#include "common/spi-dbus.h" /*---------------------------------------------------------------------------*/ -SpiAppData *app_data = NULL; +SpiBridge *spi_global_app_data = NULL; static const AtkMisc *atk_misc = NULL; @@ -57,42 +61,38 @@ static const AtkMisc *atk_misc = NULL; * Returns a 'canonicalized' value for DISPLAY, * with the screen number stripped off if present. * - * Not currently used in D-Bus version but may be - * useful in future if we make use of XAtom. */ -#if 0 -static const gchar* +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 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; } -#endif /*---------------------------------------------------------------------------*/ @@ -102,62 +102,141 @@ spi_display_name (void) * may be employed in the future for accessing the registry daemon * bus name. */ -#if 0 -static gchar * -spi_atk_bridge_get_registry_ior (void) + +static DBusConnection * +spi_atk_bridge_get_bus (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; + Atom AT_SPI_BUS; + Atom actual_type; + Display *bridge_display; + int actual_format; + unsigned char *data = NULL; + unsigned long nitems; + unsigned long leftover; + + DBusConnection *bus = NULL; + DBusError error; + + bridge_display = XOpenDisplay (spi_display_name ()); + if (!bridge_display) + g_error ("AT_SPI: Could not get the display\n"); + + AT_SPI_BUS = XInternAtom (bridge_display, "AT_SPI_BUS", False); + XGetWindowProperty (bridge_display, + XDefaultRootWindow (bridge_display), + AT_SPI_BUS, 0L, + (long) BUFSIZ, False, + (Atom) 31, &actual_type, &actual_format, + &nitems, &leftover, &data); + + dbus_error_init (&error); + + if (data == NULL) + { + g_warning + ("AT-SPI: Accessibility bus not found - Using session bus.\n"); + bus = dbus_bus_get (DBUS_BUS_SESSION, &error); + if (!bus) + g_error ("AT-SPI: Couldn't connect to bus: %s\n", error.message); + } + else + { + bus = dbus_connection_open (data, &error); + if (!bus) + { + g_error ("AT-SPI: Couldn't connect to bus: %s\n", error.message); + } + else + { + if (!dbus_bus_register (bus, &error)) + g_error ("AT-SPI: Couldn't register with bus: %s\n", error.message); + } + } + + return bus; +} + +static void +set_reply (DBusPendingCall *pending, void *user_data) +{ + void **replyptr = (void **)user_data; + + *replyptr = dbus_pending_call_steal_reply (pending); } -#endif +static DBusMessage * +send_and_allow_reentry (DBusConnection *bus, DBusMessage *message, DBusError *error) +{ + DBusPendingCall *pending; + DBusMessage *reply = NULL; + + if (!dbus_connection_send_with_reply (bus, message, &pending, -1)) + { + return NULL; + } + dbus_pending_call_set_notify (pending, set_reply, (void *)&reply, NULL); + while (!reply) + { + if (!dbus_connection_read_write_dispatch (bus, -1)) return NULL; + } + return reply; +} /*---------------------------------------------------------------------------*/ -static void -register_application (SpiAppData *app) +static gboolean +register_application (SpiBridge * app) { - DBusMessage *message; + DBusMessage *message, *reply; DBusMessageIter iter; DBusError error; - const char *uname; dbus_error_init (&error); message = dbus_message_new_method_call (SPI_DBUS_NAME_REGISTRY, - SPI_DBUS_PATH_REGISTRY, - SPI_DBUS_INTERFACE_REGISTRY, - "registerApplication"); - dbus_message_set_no_reply (message, TRUE); + SPI_DBUS_PATH_ROOT, + SPI_DBUS_INTERFACE_SOCKET, + "Embed"); + + dbus_message_iter_init_append (message, &iter); + spi_object_append_reference (&iter, app->root); + + reply = send_and_allow_reentry (app->bus, message, &error); - uname = dbus_bus_get_unique_name(app->droute.bus); + if (message) + dbus_message_unref (message); - dbus_message_iter_init_append(message, &iter); - dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &uname); - dbus_connection_send (app->droute.bus, message, NULL); - if (message) dbus_message_unref (message); + if (reply) + { + DBusMessageIter iter, iter_struct; + gchar *app_name, *obj_path; + + if (strcmp (dbus_message_get_signature (reply), "(so)") != 0) + { + g_warning ("AT-SPI: Could not obtain desktop path or name\n"); + return FALSE; + } + + dbus_message_iter_init (reply, &iter); + dbus_message_iter_recurse (&iter, &iter_struct); + dbus_message_iter_get_basic (&iter_struct, &app_name); + dbus_message_iter_next (&iter_struct); + dbus_message_iter_get_basic (&iter_struct, &obj_path); + + app->desktop_name = g_strdup (app_name); + app->desktop_path = g_strdup (obj_path); + } + else + { + g_warning ("AT-SPI: Could not embed inside desktop: %s\n", error.message); + return FALSE; + } + return TRUE; } /*---------------------------------------------------------------------------*/ static void -deregister_application (SpiAppData *app) +deregister_application (SpiBridge * app) { DBusMessage *message; DBusMessageIter iter; @@ -169,15 +248,16 @@ deregister_application (SpiAppData *app) message = dbus_message_new_method_call (SPI_DBUS_NAME_REGISTRY, SPI_DBUS_PATH_REGISTRY, SPI_DBUS_INTERFACE_REGISTRY, - "deregisterApplication"); + "DeregisterApplication"); dbus_message_set_no_reply (message, TRUE); - uname = dbus_bus_get_unique_name(app->droute.bus); + uname = dbus_bus_get_unique_name (app->bus); - dbus_message_iter_init_append(message, &iter); - dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &uname); - dbus_connection_send (app->droute.bus, message, NULL); - if (message) dbus_message_unref (message); + dbus_message_iter_init_append (message, &iter); + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &uname); + dbus_connection_send (app->bus, message, NULL); + if (message) + dbus_message_unref (message); } /*---------------------------------------------------------------------------*/ @@ -185,17 +265,17 @@ deregister_application (SpiAppData *app) static void exit_func (void) { - if (!app_data) + if (!spi_global_app_data) { return; } spi_atk_tidy_windows (); - spi_atk_deregister_event_listeners(); - deregister_application (app_data); + spi_atk_deregister_event_listeners (); + deregister_application (spi_global_app_data); - g_free(app_data); - app_data = NULL; + g_free (spi_global_app_data); + spi_global_app_data = NULL; /* Not currently creating an XDisplay */ #if 0 @@ -206,20 +286,71 @@ exit_func (void) /*---------------------------------------------------------------------------*/ -static DBusObjectPathVTable droute_vtable = +static AtkPlugClass *plug_class; +static AtkSocketClass *socket_class; + +static gchar * +get_plug_id (AtkPlug * plug) { - NULL, - &droute_message, - NULL, NULL, NULL, NULL -}; + const char *uname = dbus_bus_get_unique_name (spi_global_app_data->bus); + gchar *path; + GString *str = g_string_new (NULL); + + path = spi_register_object_to_path (spi_global_register, G_OBJECT (plug)); + g_string_printf (str, "%s:%s", uname, path); + g_free (path); + return g_string_free (str, FALSE); +} -static gchar *atspi_dbus_name; -static gboolean atspi_no_register; +static void +socket_embed_hook (AtkSocket * socket, gchar * plug_id) +{ + AtkObject *accessible = ATK_OBJECT(socket); + gchar *plug_name, *plug_path; + + /* Force registration */ + gchar *path = spi_register_object_to_path (spi_global_register, G_OBJECT (accessible)); + /* Let the plug know that it has been embedded */ + plug_name = g_strdup (plug_id); + if (!plug_name) + { + g_free (path); + return; + } + plug_path = g_utf8_strchr (plug_name + 1, -1, ':'); + if (plug_path) + { + DBusMessage *message; + *(plug_path++) = '\0'; + message = dbus_message_new_method_call (plug_name, plug_path, SPI_DBUS_INTERFACE_SOCKET, "Embedded"); + dbus_message_append_args (message, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID); + dbus_connection_send (spi_global_app_data->bus, message, NULL); + } + g_free (plug_name); + g_free (path); +} -static GOptionEntry atspi_option_entries[] = +static void +install_plug_hooks () { - {"atspi-dbus-name", 0, 0, G_OPTION_ARG_STRING, &atspi_dbus_name, "D-Bus bus name to register as", NULL}, - {"atspi-no-register", 0, 0, G_OPTION_ARG_NONE, &atspi_no_register, "Do not register with Registry Daemon", NULL}, + gpointer data; + + data = g_type_class_ref (ATK_TYPE_PLUG); + plug_class = ATK_PLUG_CLASS (data); + data = g_type_class_ref (ATK_TYPE_SOCKET); + socket_class = ATK_SOCKET_CLASS (data); + plug_class->get_object_id = get_plug_id; + socket_class->embed = socket_embed_hook; +} + +gchar *atspi_dbus_name = NULL; +static gboolean atspi_no_register = FALSE; + +static GOptionEntry atspi_option_entries[] = { + {"atspi-dbus-name", 0, 0, G_OPTION_ARG_STRING, &atspi_dbus_name, + "D-Bus bus name to register as", NULL}, + {"atspi-no-register", 0, 0, G_OPTION_ARG_NONE, &atspi_no_register, + "Do not register with Registry Daemon", NULL}, {NULL} }; @@ -234,68 +365,122 @@ static GOptionEntry atspi_option_entries[] = * */ static int -adaptor_init (gint *argc, gchar **argv[]) +adaptor_init (gint * argc, gchar ** argv[]) { GOptionContext *opt; GError *err = NULL; DBusError error; + DBusConnection *bus; + AtkObject *root; + gchar *introspection_directory; + static gboolean inited = FALSE; + + if (inited) + return 0; + + inited = TRUE; - if (app_data != NULL) - return 0; + DRoutePath *treepath, *accpath; + + root = atk_get_root (); + g_return_val_if_fail (root, 0); /* Parse command line options */ - opt = g_option_context_new(NULL); - g_option_context_add_main_entries(opt, atspi_option_entries, NULL); - g_option_context_set_ignore_unknown_options(opt, TRUE); - if (!g_option_context_parse(opt, argc, argv, &err)) - g_warning("AT-SPI Option parsing failed: %s\n", err->message); + opt = g_option_context_new (NULL); + g_option_context_add_main_entries (opt, atspi_option_entries, NULL); + g_option_context_set_ignore_unknown_options (opt, TRUE); + if (!g_option_context_parse (opt, argc, argv, &err)) + g_warning ("AT-SPI Option parsing failed: %s\n", err->message); /* Allocate global data and do ATK initializations */ - app_data = g_new0 (SpiAppData, 1); + spi_global_app_data = g_new0 (SpiBridge, 1); atk_misc = atk_misc_get_instance (); + spi_global_app_data->root = g_object_ref (root); - /* Get D-Bus connection, register D-Bus name*/ + /* Set up D-Bus connection and register bus name */ dbus_error_init (&error); - app_data->root = atk_get_root(); - app_data->droute.bus = dbus_bus_get (DBUS_BUS_SESSION, &error); - if (!app_data->droute.bus) - { - g_warning ("AT-SPI Couldn't connect to D-Bus: %s\n", error.message); - g_free(app_data); - app_data = NULL; - return 0; - } - if (atspi_dbus_name != NULL && - dbus_bus_request_name(app_data->droute.bus, atspi_dbus_name, 0, &error)) - { - g_print("AT-SPI Recieved D-Bus name - %s\n", atspi_dbus_name); - } + spi_global_app_data->bus = spi_atk_bridge_get_bus (); + if (!spi_global_app_data->bus) + { + g_free (spi_global_app_data); + spi_global_app_data = NULL; + return 0; + } - /* Finish setting up D-Bus */ - dbus_connection_setup_with_g_main(app_data->droute.bus, g_main_context_default()); + if (atspi_dbus_name != NULL) + { + if (dbus_bus_request_name + (spi_global_app_data->bus, atspi_dbus_name, 0, &error)) + { + g_print ("AT-SPI Recieved D-Bus name - %s\n", atspi_dbus_name); + } + else + { + g_print + ("AT-SPI D-Bus name requested but could not be allocated - %s\n", + atspi_dbus_name); + } + } + + dbus_connection_setup_with_g_main (spi_global_app_data->bus, + g_main_context_default ()); + + /* Hook our plug-and socket functions */ + install_plug_hooks (); + + /* + * Create the leasing, register and cache objects. + * The order is important here, the cache depends on the + * register object. + */ + spi_global_register = g_object_new (SPI_REGISTER_TYPE, NULL); + spi_global_leasing = g_object_new (SPI_LEASING_TYPE, NULL); + spi_global_cache = g_object_new (SPI_CACHE_TYPE, NULL); /* Register droute for routing AT-SPI messages */ - spi_register_tree_object(app_data->droute.bus, &app_data->droute, "/org/freedesktop/atspi/tree"); - - if (!dbus_connection_register_fallback (app_data->droute.bus, - "/org/freedesktop/atspi/accessible", - &droute_vtable, - &app_data->droute)) - { - g_warning("AT-SPI Couldn't register droute.\n"); - g_free(app_data); - app_data = NULL; - return 0; - } + spi_global_app_data->droute = + droute_new (spi_global_app_data->bus); + + treepath = droute_add_one (spi_global_app_data->droute, + "/org/a11y/atspi/cache", spi_global_cache); + + if (!treepath) + { + g_warning ("atk-bridge: Error in droute_add_one(). Already running?"); + return 0; + } + + accpath = droute_add_many (spi_global_app_data->droute, + "/org/a11y/atspi/accessible", + NULL, + (DRouteGetDatumFunction) + spi_global_register_path_to_object); + /* Register all interfaces with droute and set up application accessible db */ - atk_dbus_initialize (&app_data->droute); + spi_initialize_cache (treepath); + spi_initialize_accessible (accpath); + spi_initialize_application (accpath); + spi_initialize_action (accpath); + spi_initialize_collection (accpath); + spi_initialize_component (accpath); + spi_initialize_document (accpath); + spi_initialize_editabletext (accpath); + spi_initialize_hyperlink (accpath); + spi_initialize_hypertext (accpath); + spi_initialize_image (accpath); + spi_initialize_selection (accpath); + spi_initialize_socket (accpath); + spi_initialize_table (accpath); + spi_initialize_text (accpath); + spi_initialize_value (accpath); /* Register methods to send D-Bus signals on certain ATK events */ spi_atk_register_event_listeners (); /* Register this app by sending a signal out to AT-SPI registry daemon */ - register_application (app_data); + if (!atspi_no_register && (!root || !ATK_IS_PLUG (root))) + register_application (spi_global_app_data); g_atexit (exit_func); @@ -305,9 +490,38 @@ adaptor_init (gint *argc, gchar **argv[]) /*---------------------------------------------------------------------------*/ int -gtk_module_init (gint *argc, gchar **argv[]) +gtk_module_init (gint * argc, gchar ** argv[]) +{ + const gchar *load_bridge = g_getenv ("NO_AT_BRIDGE"); + + if (!load_bridge || g_ascii_strtod (load_bridge, NULL) == 0) + { + return adaptor_init (argc, argv); + } + return 0; +} + +void +gnome_accessibility_module_init (void) +{ + const gchar *load_bridge = g_getenv ("NO_AT_BRIDGE"); + + if (!load_bridge || g_ascii_strtod (load_bridge, NULL) == 0) + { + adaptor_init (NULL, NULL); + + if (g_getenv ("AT_SPI_DEBUG")) + { + g_print ("Atk Accessibility bridge initialized\n"); + } + } +} + +void +gnome_accessibility_module_shutdown (void) { - return adaptor_init (argc, argv); + spi_atk_deregister_event_listeners (); + exit_func (); } /*END------------------------------------------------------------------------*/