X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=atk-adaptor%2Fbridge.c;h=e1782aa2ccc9e8ccf0b6b7b34a3ad002f8029277;hb=3e1f56f6e2c63ad90e13214ac13a2dc848e925b5;hp=5560d9518939645a383282a36185f87bdddd403f;hpb=730e1e05bdb0eb48b67fcaa671ca2be6ef57a689;p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git diff --git a/atk-adaptor/bridge.c b/atk-adaptor/bridge.c index 5560d95..e1782aa 100644 --- a/atk-adaptor/bridge.c +++ b/atk-adaptor/bridge.c @@ -2,6 +2,7 @@ * AT-SPI - Assistive Technology Service Provider Interface * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap) * + * Copyright 2008, 2009 Codethink Ltd. * Copyright 2001, 2002, 2003 Sun Microsystems Inc., * Copyright 2001, 2002, 2003 Ximian, Inc. * @@ -26,291 +27,45 @@ #include #include -#include -#include #include #include #include #include -#include -#include -#include "accessible.h" -#include "bridge.h" -#include "atk-dbus.h" - -#undef SPI_BRIDGE_DEBUG - -#define DBG(a,b) if(_dbg>=(a))b - -int _dbg = 0; -static const char *registry = NULL; -SpiAppData *this_app = NULL; -static gboolean registry_died = FALSE; -static gint toplevels = 0; -static gboolean exiting = FALSE; -static AtkMisc *misc = NULL; -static gboolean during_init_shutdown = TRUE; - -static const char *spi_atk_bridge_get_registry (void); -static char *device_event_controller = NULL; -static void spi_atk_bridge_register_application (const char *registry); -static gchar *spi_atk_bridge_get_registry_ior (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_tidy_windows (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; - -/* - * These exported symbols are hooked by gnome-program - * to provide automatic module initialization and shutdown. - */ -extern void gnome_accessibility_module_init (void); -extern void gnome_accessibility_module_shutdown (void); - -void -spi_atk_register_event_listeners(void); - -void -spi_atk_deregister_event_listeners (void); - -static gboolean -post_init (gpointer data) -{ - during_init_shutdown = FALSE; - return FALSE; -} - -static DBusObjectPathVTable droute_vtable = -{ - NULL, - &droute_message, - NULL, NULL, NULL, NULL -}; - -static gchar* atspi_dbus_name; -static gboolean atspi_no_register; -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} -}; +#include -static SpiAppData * -spi_app_init (AtkObject *root, gint *argc, gchar **argv[]) -{ - GOptionContext *opt; - SpiAppData *ad = g_new0(SpiAppData, 1); - GError *err = NULL; - DBusError error; - int i; - - 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("Option parsing failed: %s\n", err->message); - - dbus_error_init(&error); - ad->root = root; - ad->droute.bus = dbus_bus_get(DBUS_BUS_SESSION, &error); - g_print("D-Bus unique name is : %s\n", dbus_bus_get_unique_name(ad->droute.bus)); - - if (!ad->droute.bus) - { - g_warning("Couldn't connect to dbus: %s\n", error.message); - free(ad); - return NULL; - } - if (atspi_dbus_name != NULL && dbus_bus_request_name(ad->droute.bus, - atspi_dbus_name, - 0, - &error)) - { - g_print("\nRecieved D-Bus name - %s\n", atspi_dbus_name); - } - spi_register_tree_object(ad->droute.bus, &ad->droute, "/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"); - free(ad); - return NULL; - } - - dbus_connection_setup_with_g_main(ad->droute.bus, g_main_context_default()); - - atk_dbus_initialize (&ad->droute); - 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 (); - - misc = atk_misc_get_instance(); +#include "bridge.h" +#include "event.h" +#include "accessible-register.h" +#include "adaptors.h" - if (g_getenv ("ATK_BRIDGE_REDIRECT_LOG")) - { - fname = g_strconcat ("/tmp/", g_get_prgname (), ".at-spi-log", NULL); - /* make sure we're not being redirected - security issue */ - if (!g_file_test (fname, G_FILE_TEST_IS_SYMLINK)) - freopen (fname, "w", stderr); - g_free (fname); - } +#include "common/spi-dbus.h" - if (debug_env_string) - _dbg = (int) g_ascii_strtod (debug_env_string, NULL); - - /* Connect to dbus */ - this_app = spi_app_init (atk_get_root (), argc, argv); - - /* - * 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) +/* + * Provides the path for the introspection directory. + */ +#if !defined ATSPI_INTROSPECTION_PATH + #error "No introspection XML directory defined" #endif - { - DBG (1, g_message ("Found Bonobo component\n")); - 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 - { - 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 (); - } - else - { - atk_bridge_initialized = FALSE; - } - g_idle_add (post_init, NULL); - - return 0; -} - -static gboolean -spi_atk_bridge_do_registration (void) -{ - if (spi_atk_bridge_get_registry () == NULL) - { - g_warning ("Could not locate registry"); - return FALSE; - } - /* Create the accessible application server object */ - if (this_app == NULL) - this_app = spi_app_init (atk_get_root (), 0, NULL); +/*---------------------------------------------------------------------------*/ - DBG (1, g_message ("About to register application\n")); +SpiAppData *atk_adaptor_app_data = NULL; - spi_atk_bridge_register_application (spi_atk_bridge_get_registry ()); - - g_atexit (spi_atk_bridge_exit_func); +static const AtkMisc *atk_misc = NULL; - DBG (1, g_message ("Application registered & listening\n")); - return TRUE; -} +/*static Display *bridge_display = NULL;*/ -static void -spi_atk_bridge_toplevel_added (AtkObject *object, - guint index, - AtkObject *child) -{ - if (toplevels == 0) - { - spi_atk_bridge_do_registration (); - } - toplevels++; -} +/*---------------------------------------------------------------------------*/ -static void -spi_atk_bridge_toplevel_removed (AtkObject *object, - guint index, - AtkObject *child) -{ - 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 void -spi_atk_bridge_register_application (const char *registry) -{ - DBusMessage *message, *reply; - DBusError error; - - message = dbus_message_new_method_call (SPI_DBUS_NAME_REGISTRY, SPI_DBUS_PATH_REGISTRY, SPI_DBUS_INTERFACE_REGISTRY, "registerApplication"); - dbus_error_init (&error); - reply = dbus_connection_send_with_reply_and_block(this_app->droute.bus, message, 1000, &error); - if (error.message) g_print (error.message); - if (reply) dbus_message_unref (reply); - if (message) dbus_message_unref (message); -} - -/* +/* * 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* spi_display_name (void) { @@ -318,37 +73,44 @@ spi_display_name (void) 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; - } + 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 -static Display *bridge_display = NULL; +/*---------------------------------------------------------------------------*/ +/* + * Gets the IOR from the XDisplay. + * Not currently used in D-Bus version, but something similar + * may be employed in the future for accessing the registry daemon + * bus name. + */ +#if 0 static gchar * spi_atk_bridge_get_registry_ior (void) { - Atom AT_SPI_IOR; Atom actual_type; int actual_format; @@ -360,124 +122,295 @@ spi_atk_bridge_get_registry_ior (void) 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); + 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.")); - + g_warning (_("AT_SPI_REGISTRY was not started at session startup.")); return (gchar *) data; - } +#endif -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"; -} +/*---------------------------------------------------------------------------*/ -static const char * -spi_atk_bridge_get_dec (void) +static void +register_application (SpiAppData *app) { - return "/dec"; -} + DBusMessage *message; + DBusMessageIter iter; + DBusError error; + const char *uname; -int -gtk_module_init (gint *argc, gchar **argv[]) -{ - //printf("Pointer to argc %x %x\n", (short) ((argc && 0xffff0000) >> 16), (short) (argc && 0xffff)); - return atk_bridge_init (argc, argv); + 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); + + 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->bus, message, NULL); + if (message) dbus_message_unref (message); } +/*---------------------------------------------------------------------------*/ + static void deregister_application (SpiAppData *app) { - const char *registry = spi_atk_bridge_get_registry (); - // todo: deregister + DBusMessage *message; + 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, + "DeregisterApplication"); + dbus_message_set_no_reply (message, TRUE); + + 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->bus, message, NULL); + if (message) dbus_message_unref (message); } +/*---------------------------------------------------------------------------*/ + static void -spi_atk_bridge_exit_func (void) +exit_func (void) { - SpiAppData *app = (SpiAppData *) this_app; - - DBG (1, g_message ("exiting bridge\n")); - - if (!app) + if (!atk_adaptor_app_data) { return; } - if (atk_bridge_pid != getpid ()) - { - _exit (0); - } - during_init_shutdown = TRUE; - exiting = TRUE; - /* - * Check whether we still have windows which have not been deleted. - */ spi_atk_tidy_windows (); - /* - * FIXME: this may be incorrect for apps that do their own bonobo - * shutdown, until we can explicitly shutdown to get the ordering - * right. - */ - 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")) - { - } + spi_atk_deregister_event_listeners(); + deregister_application (atk_adaptor_app_data); + + g_free(atk_adaptor_app_data); + atk_adaptor_app_data = NULL; + + /* Not currently creating an XDisplay */ +#if 0 if (bridge_display) XCloseDisplay (bridge_display); +#endif } -void -gnome_accessibility_module_init (void) +/*---------------------------------------------------------------------------*/ + +#ifdef __ATK_PLUG_H__ +static AtkPlugClass *plug_class; +static AtkSocketClass *socket_class; + +static gchar * +get_plug_id (AtkPlug *plug) { - atk_bridge_init (0, NULL); + const char *uname = dbus_bus_get_unique_name(atk_adaptor_app_data->bus); + gchar *path; + GString *str = g_string_new (NULL); + + path = atk_dbus_object_to_path (ATK_OBJECT(plug), TRUE); + g_string_printf (str, "%s:%s", uname, path); + g_free (path); + return g_string_free (str, FALSE); +} - if (g_getenv ("AT_BRIDGE_SHUTDOWN")) - { - g_print("Atk Accessibility bridge initialized\n"); - } +static void +socket_embed_hook (AtkSocket *socket, gchar *plug_id) +{ + AtkObject *accessible = ATK_OBJECT(socket); + /* Force registration */ + gchar *path = atk_dbus_object_to_path (accessible, TRUE); + spi_emit_cache_update (accessible, atk_adaptor_app_data->bus); + g_free (path); } -void -gnome_accessibility_module_shutdown (void) +static void +install_plug_hooks () { - int i; + gpointer data; - if (!atk_bridge_initialized) - { - return; - } - during_init_shutdown = TRUE; - atk_bridge_initialized = FALSE; + 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; +} +#endif + +static gchar *atspi_dbus_name; +static gboolean atspi_no_register; + +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} +}; - if (g_getenv ("AT_BRIDGE_SHUTDOWN")) +/* + * spi_app_init + * + * The following needs to be initialized. + * + * - DRoute for routing message to their accessible objects. + * - Event handlers for emmitting signals on specific ATK events. + * - Application registration with the AT-SPI registry. + * + */ +static int +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; + + 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); + + /* Allocate global data and do ATK initializations */ + atk_adaptor_app_data = g_new0 (SpiAppData, 1); + atk_misc = atk_misc_get_instance (); + atk_adaptor_app_data->root = root; + + /* Set up D-Bus connection and register bus name */ + dbus_error_init (&error); + atk_adaptor_app_data->bus = dbus_bus_get (DBUS_BUS_SESSION, &error); + if (!atk_adaptor_app_data->bus) + { + g_warning ("AT-SPI Couldn't connect to D-Bus: %s\n", error.message); + g_free(atk_adaptor_app_data); + atk_adaptor_app_data = NULL; + return 0; + } + if (atspi_dbus_name != NULL && + dbus_bus_request_name(atk_adaptor_app_data->bus, atspi_dbus_name, 0, &error)) + { + g_print("AT-SPI Recieved D-Bus name - %s\n", atspi_dbus_name); + } + + dbus_connection_setup_with_g_main(atk_adaptor_app_data->bus, g_main_context_default()); + + /* Get D-Bus introspection directory */ + introspection_directory = (char *) g_getenv("ATSPI_INTROSPECTION_PATH"); + if (introspection_directory == NULL) + introspection_directory = ATSPI_INTROSPECTION_PATH; + + /* Register droute for routing AT-SPI messages */ + atk_adaptor_app_data->droute = droute_new (atk_adaptor_app_data->bus, introspection_directory); + + treepath = droute_add_one (atk_adaptor_app_data->droute, + "/org/freedesktop/atspi/tree", + NULL); + + accpath = droute_add_many (atk_adaptor_app_data->droute, + "/org/freedesktop/atspi/accessible", + NULL, + (DRouteGetDatumFunction) atk_dbus_path_to_gobject); + + /* Register all interfaces with droute and set up application accessible db */ + spi_initialize_tree (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_table (accpath); + spi_initialize_text (accpath); + spi_initialize_value (accpath); + + /* Initialize the AtkObject registration */ + atk_dbus_initialize (atk_adaptor_app_data->root); + + /* Register methods to send D-Bus signals on certain ATK events */ + spi_atk_register_event_listeners (); + +#ifdef __ATK_PLUG_H__ + /* Hook our plug-and socket functions */ + install_plug_hooks (); +#endif + + /* Register this app by sending a signal out to AT-SPI registry daemon */ + register_application (atk_adaptor_app_data); + + g_atexit (exit_func); + + return 0; +} + +/*---------------------------------------------------------------------------*/ + +int +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) { - g_print("Atk Accessibility bridge shutdown\n"); + return adaptor_init (argc, argv); } + return 0; +} - spi_atk_deregister_event_listeners(); +void +gnome_accessibility_module_init (void) +{ + const gchar *load_bridge = g_getenv ("NO_AT_BRIDGE"); - deregister_application (this_app); - this_app = NULL; + if (!load_bridge || g_ascii_strtod (load_bridge, NULL) == 0) + { + adaptor_init (NULL, NULL); - misc = NULL; + if (g_getenv ("AT_SPI_DEBUG")) + { + g_print("Atk Accessibility bridge initialized\n"); + } + } } -static void -reinit_register_vars (void) +void +gnome_accessibility_module_shutdown (void) { - registry = NULL; - device_event_controller = NULL; - this_app = NULL; + spi_atk_deregister_event_listeners (); + exit_func (); } +/*END------------------------------------------------------------------------*/