From: Mark Doffman Date: Tue, 4 Nov 2008 19:34:23 +0000 (+0000) Subject: Temporary commit. Non working changes to the registration X-Git-Tag: AT_SPI2_ATK_2_12_0~579^2 X-Git-Url: http://review.tizen.org/git/?p=platform%2Fcore%2Fuifw%2Fat-spi2-atk.git;a=commitdiff_plain;h=f01ffde94695198fe9e68df3b07eea59d563c495 Temporary commit. Non working changes to the registration method used by registryd. --- diff --git a/atk-adaptor/bridge.c b/atk-adaptor/bridge.c index 9c37fe5..3e5fba4 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 Codethink Ltd. * Copyright 2001, 2002, 2003 Sun Microsystems Inc., * Copyright 2001, 2002, 2003 Ximian, Inc. * @@ -38,278 +39,28 @@ #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; +void spi_atk_register_event_listeners (void); +void spi_atk_deregister_event_listeners (void); +void spi_atk_tidy_windows (void); -/* - * 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 -}; +SpiAppData *app_data = NULL; -static gchar* atspi_dbus_name; -static gboolean atspi_no_register; +static const AtkMisc *atk_misc = NULL; -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} -}; +/*static Display *bridge_display = NULL;*/ -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(); - - if (g_getenv ("ATK_BRIDGE_REDIRECT_LOG")) - { - fname = g_strconcat ("/tmp/", g_get_prgname (), ".at-spi-log", NULL); - /* make sure we're not being redirected - security issue */ - if (!g_file_test (fname, G_FILE_TEST_IS_SYMLINK)) - freopen (fname, "w", stderr); - g_free (fname); - } - - if (debug_env_string) - _dbg = (int) g_ascii_strtod (debug_env_string, NULL); - - /* 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) -#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")); - - spi_atk_bridge_register_application (spi_atk_bridge_get_registry ()); - - g_atexit (spi_atk_bridge_exit_func); - - DBG (1, g_message ("Application registered & listening\n")); - return TRUE; -} - -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_signal (SPI_DBUS_PATH_REGISTRY, SPI_DBUS_INTERFACE_TREE, "registerApplication"); - dbus_error_init (&error); - dbus_connection_send (this_app->droute.bus, message, NULL); - if (error.message) g_print (error.message); - 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) { @@ -317,37 +68,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; @@ -359,124 +117,197 @@ 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->droute.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); } +/*---------------------------------------------------------------------------*/ + 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->droute.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); } +/*---------------------------------------------------------------------------*/ + 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 (!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 (app_data); + + g_free(app_data); + app_data = NULL; + + /* Not currently creating an XDisplay */ +#if 0 if (bridge_display) XCloseDisplay (bridge_display); +#endif } -void -gnome_accessibility_module_init (void) +/*---------------------------------------------------------------------------*/ + +static DBusObjectPathVTable droute_vtable = { - atk_bridge_init (0, NULL); + NULL, + &droute_message, + NULL, NULL, NULL, NULL +}; - if (g_getenv ("AT_BRIDGE_SHUTDOWN")) - { - g_print("Atk Accessibility bridge initialized\n"); - } -} +static gchar *atspi_dbus_name; +static gboolean atspi_no_register; -void -gnome_accessibility_module_shutdown (void) +static GOptionEntry atspi_option_entries[] = { - int i; - - if (!atk_bridge_initialized) - { - return; - } - during_init_shutdown = TRUE; - atk_bridge_initialized = FALSE; + {"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")) - { - g_print("Atk Accessibility bridge shutdown\n"); - } +/* + * 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; - spi_atk_deregister_event_listeners(); + if (app_data != NULL) + return 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 */ + app_data = g_new0 (SpiAppData, 1); + atk_misc = atk_misc_get_instance (); + + /* Get D-Bus connection, register D-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); + } - deregister_application (this_app); - this_app = NULL; + /* Finish setting up D-Bus */ + dbus_connection_setup_with_g_main(app_data->droute.bus, g_main_context_default()); - misc = 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; + } + + /* Register all interfaces with droute and set up application accessible db */ + atk_dbus_initialize (&app_data->droute); + + /* 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); + + g_atexit (exit_func); + + return 0; } -static void -reinit_register_vars (void) +/*---------------------------------------------------------------------------*/ + +int +gtk_module_init (gint *argc, gchar **argv[]) { - registry = NULL; - device_event_controller = NULL; - this_app = NULL; + return adaptor_init (argc, argv); } + +/*END------------------------------------------------------------------------*/ diff --git a/atk-adaptor/event.c b/atk-adaptor/event.c index a4cbd9d..ddc3536 100644 --- a/atk-adaptor/event.c +++ b/atk-adaptor/event.c @@ -28,7 +28,7 @@ #include "bridge.h" #include "atk-dbus.h" -extern SpiAppData *this_app; +extern SpiAppData *app_data; static GArray *listener_ids = NULL; @@ -61,7 +61,7 @@ Accessibility_DeviceEventController_notifyListenersSync(const Accessibility_Devi dbus_error_init(&error); if (spi_dbus_marshal_deviceEvent(message, key_event)) { - DBusMessage *reply = dbus_connection_send_with_reply_and_block(this_app->droute.bus, message, 1000, &error); + DBusMessage *reply = dbus_connection_send_with_reply_and_block(app_data->droute.bus, message, 1000, &error); if (reply) { DBusError error; @@ -226,7 +226,7 @@ emit(AtkObject *accessible, dbus_message_iter_append_basic(&sub, (int) *type, &val); dbus_message_iter_close_container(&iter, &sub); - dbus_connection_send(this_app->droute.bus, sig, NULL); + dbus_connection_send(app_data->droute.bus, sig, NULL); dbus_message_unref(sig); } @@ -279,7 +279,7 @@ emit_rect(AtkObject *accessible, dbus_message_iter_close_container (&variant, &sub); dbus_message_iter_close_container (&iter, &variant); - dbus_connection_send(this_app->droute.bus, sig, NULL); + dbus_connection_send(app_data->droute.bus, sig, NULL); } /*---------------------------------------------------------------------------*/ diff --git a/atk-adaptor/tree.c b/atk-adaptor/tree.c index 00ec003..8652f77 100644 --- a/atk-adaptor/tree.c +++ b/atk-adaptor/tree.c @@ -28,7 +28,7 @@ #include "accessible.h" #include "bridge.h" -extern SpiAppData *this_app; +extern SpiAppData *app_data; static gboolean update_pending = FALSE; /*---------------------------------------------------------------------------*/ @@ -58,7 +58,7 @@ append_accessible(gpointer ref, gpointer obj_data, gpointer iter) obj = ATK_OBJECT(obj_data); iter_array = (DBusMessageIter *) iter; - data = &(this_app->droute); + data = &(app_data->droute); dbus_message_iter_open_container (iter_array, DBUS_TYPE_STRUCT, NULL, &iter_struct); { @@ -163,7 +163,7 @@ send_cache_update(gpointer d) DBusMessageIter iter_array; DRouteData *data; - data = &(this_app->droute); + data = &(app_data->droute); message = dbus_message_new_signal ("/org/freedesktop/atspi/tree", SPI_DBUS_INTERFACE_TREE, "updateTree"); diff --git a/pyatspi/applicationcache.py b/pyatspi/applicationcache.py index b6676d2..bed6a89 100644 --- a/pyatspi/applicationcache.py +++ b/pyatspi/applicationcache.py @@ -12,14 +12,17 @@ #along with this program; if not, write to the Free Software #Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +import dbus + from accessiblecache import AccessibleCache from desktop import Desktop from factory import accessible_factory +from event import Event as _Event import interfaces __all__ = [ - + "ApplicationCache", "TestApplicationCache", ] @@ -92,4 +95,118 @@ class TestApplicationCache(object): """ return self._connection +#------------------------------------------------------------------------------ + +class ApplicationCache(object): + """ + Test application store, accesses a single application. + + The store object acts as a central class for creating accessible objects. + It interfaces with the ATSPI registry to keep account of all accessible + applications. It contains the accessible cache objects from each application. + + @registry: Each accessible cache object must have a reference to the registry + object to send update events. + + @connection: D-Bus connection used to access applications. + + @bus_name: The test store only accesses one accessible application, this is its + D-Bus path. + """ + + _REGISTRY_PATH = '/org/freedesktop/atspi/registry' + _REGISTRY_INTERFACE = 'org.freedesktop.atspi.Registry' + _REGISTRY_NAME = 'org.freedesktop.atspi.Registry' + + # An accessible path of '/' implies the desktop object, whatever the application name. + _DESKTOP_PATH = '/' + + _APPLICATIONS_ADD = 1 + _APPLICATIONS_REMOVE = 0 + + def __init__(self, registry, connection): + self._connection = connection + self._registry = registry + + self.application_list = [] + self.application_cache = {} + + self._regsig = connection.add_signal_receiver(self.update_handler, + dbus_interface=ApplicationCache._REGISTRY_INTERFACE, + signal_name="updateApplications") + + obj = connection.get_object(ApplicationCache._REGISTRY_NAME, + ApplicationCache._REGISTRY_PATH, + introspect=False) + self._app_register = dbus.Interface(obj, ApplicationCache._REGISTRY_INTERFACE) + + self.application_list.extend(self._app_register.getApplications()) + + def update_handler (self, update_type, bus_name): + if update_type == ApplicationCache._APPLICATIONS_ADD: + #TODO Check that app does not already exist + self.application_list.append(bus_name) + self.application_cache[bus_name] = AccessibleCache(self._registry, self._connection, bus_name) + event = _Event(self, + ApplicationCache._DESKTOP_PATH, + ApplicationCache._REGISTRY_NAME, + "org.freedesktop.atspi.Event.Object", + "children-changed", + ("", 0, 0, "")) + elif update_type == ApplicationCache._APPLICATIONS_REMOVE: + #TODO Fail safely if app does not exist + self.application_list.remove(bus_name) + del(self.application_cache[bus_name]) + event = _Event(self, + ApplicationCache._DESKTOP_PATH, + ApplicationCache._REGISTRY_NAME, + "org.freedesktop.atspi.Event.Object", + "children-changed", + ("", 0, 0, "")) + + self._registry._notifyChildrenChange(event) + + def get_cache_data(self, app_name, acc_path): + """ + Returns the cache tuple for the given application and accessible + object path. Throws an IndexError if the cache data is not found. + """ + return self.application_cache[app_name][acc_path] + + def create_application(self, app_name): + """ + Creates an accessible object for the root of the application + available at the given D-Bus name. + """ + cls = accessible_factory.get_accessible_class(interfaces.ATSPI_APPLICATION) + return cls(app_name, self.application_cache[app_name].root, self, interfaces.ATSPI_APPLICATION) + + def create_accessible(self, app_name, acc_path, interface, dbus_object=None): + """ + Creates an accessible object. + + @app_name: D-Bus name of the application where the accessible object resides. + + @acc_path: D-Bus path of the object within the application. + + @interface: D-Bus interface of the requested object. A different accessible object + class will be created depending on this. Making the function much like + an accessible object factory. + + @dbus_object: If a D-Bus object already exists for the accessible object it can be + provided here so that another one is not created. + """ + if acc_path == ApplicationCache._DESKTOP_PATH: + return Desktop(self) + else: + cls = accessible_factory.get_accessible_class(interface) + return cls(app_name, acc_path, self, interface, dbus_object=dbus_object) + + @property + def connection(self): + """ + D-Bus connection used by the store. + """ + return self._connection + #END---------------------------------------------------------------------------- diff --git a/pyatspi/registry.py b/pyatspi/registry.py index 0c40fcf..a795f1f 100644 --- a/pyatspi/registry.py +++ b/pyatspi/registry.py @@ -27,7 +27,7 @@ from base import Enum as _Enum from desktop import Desktop as _Desktop from event import EventType as _EventType from event import event_type_to_signal_reciever as _event_type_to_signal_reciever -from applicationcache import TestApplicationCache +from applicationcache import TestApplicationCache, ApplicationCache from dbus.mainloop.glib import DBusGMainLoop as _DBusGMainLoop _DBusGMainLoop(set_as_default=True) @@ -123,8 +123,6 @@ class _Registry(object): @type observers: dictionary """ - _REGISTRY_NAME = 'org.freedesktop.atspi.Registry' - def __init__(self): """ Stores a reference to the AT-SPI registry. Gets and stores a reference @@ -141,6 +139,8 @@ class _Registry(object): if app_name: self._app_name = app_name self._appcache = TestApplicationCache(self, self._bus, app_name) + else: + self._appcache = ApplicationCache(self, self._bus) self._event_listeners = {} diff --git a/registryd/registry.c b/registryd/registry.c index b5610fe..2ef53d0 100644 --- a/registryd/registry.c +++ b/registryd/registry.c @@ -28,6 +28,12 @@ #include "registry.h" +enum +{ + REGISTRY_APPLICATION_REMOVE = 0, + REGISTRY_APPLICATION_ADD = 1 +}; + /*---------------------------------------------------------------------------*/ G_DEFINE_TYPE(SpiRegistry, spi_registry, G_TYPE_OBJECT) @@ -59,57 +65,38 @@ static void emit(SpiRegistry *reg, const char *itf, const char *name, int ftype, /*---------------------------------------------------------------------------*/ -static void -add_bus_name_cb (gpointer item, gpointer data) +static gint +data_str_cmp (gpointer a, gpointer b, gpointer data) { - DBusMessageIter *iter_array = (DBusMessageIter *) data; - - dbus_message_iter_append_basic (iter_array, DBUS_TYPE_STRING, (gchar **) &item); + return g_strcmp0(a, b); } -static DBusMessage * -impl_getApplications (DBusConnection *bus, DBusMessage *message, void *user_data) +static gboolean +seq_add_string (GSequence *seq, gchar *str) { - DBusMessage *reply; - DBusMessageIter iter, iter_array; - SpiRegistry *reg = SPI_REGISTRY (user_data); - - reply = dbus_message_new_method_return (message); - - dbus_message_iter_init_append (reply, &iter); - dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &iter_array); - g_sequence_foreach (reg->apps, add_bus_name_cb, &iter_array); - dbus_message_iter_close_container(&iter, &iter_array); - return reply; -} + GSequenceIter *iter; + gchar *item; + gboolean res = FALSE; -static DBusHandlerResult -message_handler (DBusConnection *bus, DBusMessage *message, void *user_data) -{ - DBusMessage *reply = NULL; + iter = g_sequence_search (seq, str, (GCompareDataFunc) data_str_cmp, NULL); + iter = g_sequence_iter_prev (iter); - if (dbus_message_is_method_call (message, SPI_DBUS_INTERFACE_REGISTRY, "getApplications")) + if (!g_sequence_iter_is_end (iter)) { - reply = impl_getApplications (bus, message, user_data); - if (reply) + item = g_sequence_get (iter); + if (g_strcmp0 (item, str)) { - dbus_connection_send (bus, reply, NULL); - dbus_message_unref (reply); + g_sequence_insert_sorted (seq, g_strdup(str), (GCompareDataFunc) data_str_cmp, NULL); + res = TRUE; } - return DBUS_HANDLER_RESULT_HANDLED; } else { - return DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + g_sequence_insert_sorted (seq, g_strdup(str), (GCompareDataFunc) data_str_cmp, NULL); + res = TRUE; } -} -/*---------------------------------------------------------------------------*/ - -static gint -data_str_cmp (gpointer a, gpointer b, gpointer data) -{ - return g_strcmp0(a, b); + return res; } static gboolean @@ -135,25 +122,128 @@ seq_remove_string (GSequence *seq, gchar *str) } static void -handle_register_application (SpiRegistry *reg, DBusMessage *message) +add_application (DBusConnection *bus, SpiRegistry *reg, gchar *app) +{ + guint add = REGISTRY_APPLICATION_ADD; + + if (seq_add_string (reg->apps, app)) + { + emit (reg, + SPI_DBUS_INTERFACE_REGISTRY, + "updateApplications", + DBUS_TYPE_INT32, + &add, + DBUS_TYPE_STRING, + &app, + DBUS_TYPE_INVALID); + } +} + +static void +remove_application (DBusConnection *bus, SpiRegistry *reg, gchar *app) +{ + guint remove = REGISTRY_APPLICATION_REMOVE; + + if (seq_remove_string (reg->apps, app)) + { + /*TODO spi_remove_device_listeners (registry->de_controller, old);*/ + emit (reg, + SPI_DBUS_INTERFACE_REGISTRY, + "updateApplications", + DBUS_TYPE_INT32, + &remove, + DBUS_TYPE_STRING, + &app, + DBUS_TYPE_INVALID); + } +} + +/*---------------------------------------------------------------------------*/ + +static void +add_bus_name_cb (gpointer item, gpointer data) +{ + DBusMessageIter *iter_array = (DBusMessageIter *) data; + + dbus_message_iter_append_basic (iter_array, DBUS_TYPE_STRING, (gchar **) &item); +} + +static DBusMessage * +impl_getApplications (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + DBusMessage *reply; + DBusMessageIter iter, iter_array; + SpiRegistry *reg = SPI_REGISTRY (user_data); + + reply = dbus_message_new_method_return (message); + + dbus_message_iter_init_append (reply, &iter); + dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, "s", &iter_array); + g_sequence_foreach (reg->apps, add_bus_name_cb, &iter_array); + dbus_message_iter_close_container(&iter, &iter_array); + return reply; +} + +/*---------------------------------------------------------------------------*/ + +static void +impl_registerApplication (DBusConnection *bus, DBusMessage *message, void *user_data) { gchar *app_name; + SpiRegistry *reg = SPI_REGISTRY (user_data); if (dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &app_name, DBUS_TYPE_INVALID)) - g_sequence_insert_sorted (reg->apps, app_name, (GCompareDataFunc) data_str_cmp, NULL); + add_application(bus, reg, app_name); } static void -handle_deregister_application (SpiRegistry *reg, DBusMessage *message) +impl_deregisterApplication (DBusConnection *bus, DBusMessage *message, void *user_data) { gchar *app_name; + SpiRegistry *reg = SPI_REGISTRY (user_data); if (dbus_message_get_args (message, NULL, DBUS_TYPE_STRING, &app_name, DBUS_TYPE_INVALID)) - seq_remove_string (reg->apps, app_name); + remove_application(bus, reg, app_name); } +/*---------------------------------------------------------------------------*/ + +static DBusHandlerResult +message_handler (DBusConnection *bus, DBusMessage *message, void *user_data) +{ + DBusMessage *reply = NULL; + guint res = DBUS_HANDLER_RESULT_HANDLED; + + + int mtype; + const char *itf; + const char *name; + + mtype = dbus_message_get_type (message); + itf = dbus_message_get_interface (message); + name = dbus_message_get_member (message); + + if (dbus_message_is_method_call (message, SPI_DBUS_INTERFACE_REGISTRY, "getApplications")) + reply = impl_getApplications (bus, message, user_data); + else if (dbus_message_is_method_call (message, SPI_DBUS_INTERFACE_REGISTRY, "registerApplication")) + impl_registerApplication (bus, message, user_data); + else if (dbus_message_is_method_call (message, SPI_DBUS_INTERFACE_REGISTRY, "deregisterApplication")) + impl_deregisterApplication (bus, message, user_data); + else + res = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; + + if (reply) + { + dbus_connection_send (bus, reply, NULL); + dbus_message_unref (reply); + } + return res; +} + +/*---------------------------------------------------------------------------*/ + static void -handle_disconnection (SpiRegistry *reg, DBusMessage *message) +handle_disconnection (DBusConnection *bus, SpiRegistry *reg, DBusMessage *message) { char *name, *old, *new; @@ -162,17 +252,12 @@ handle_disconnection (SpiRegistry *reg, DBusMessage *message) DBUS_TYPE_STRING, &old, DBUS_TYPE_STRING, &new, DBUS_TYPE_INVALID)) - { - if (*old != '\0' && *new == '\0') { - if (seq_remove_string (reg->apps, old)) + if (*old != '\0' && *new == '\0') { - /*Emit deregistered signal here*/ - emit (reg, SPI_DBUS_INTERFACE_TREE, "deregisterApplication", DBUS_TYPE_STRING, old); - /*TODO spi_remove_device_listeners (registry->de_controller, old);*/ + remove_application(bus, reg, old); } } - } } static DBusHandlerResult @@ -183,27 +268,8 @@ signal_handler (DBusConnection *bus, DBusMessage *message, void *user_data) const char *iface = dbus_message_get_interface (message); const char *member = dbus_message_get_member (message); - g_print ("\n%s", iface); - g_print ("\n%d", dbus_message_get_type (message)); - g_print ("\n%s\n", member); - -#if 0 - if (dbus_message_is_signal (message, DBUS_INTERFACE_DBUS, "NameOwnerChanged")) - handle_disconnection (registry, message); - else if (dbus_message_is_signal (message, SPI_DBUS_INTERFACE_TREE, "registerApplication")) - handle_register_application (registry, message); - else if (dbus_message_is_signal (message, SPI_DBUS_INTERFACE_TREE, "deregisterApplication")) - handle_deregister_application (registry, message); - else - res = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; -#endif - if (!g_strcmp0(iface, DBUS_INTERFACE_DBUS) && !g_strcmp0(member, "NameOwnerChanged")) - handle_disconnection (registry, message); - else if (!g_strcmp0(iface, SPI_DBUS_INTERFACE_TREE) && !g_strcmp0(member, "registerApplication")) - handle_register_application (registry, message); - else if (!g_strcmp0(iface, SPI_DBUS_INTERFACE_TREE) && !g_strcmp0(member, "deregisterApplication")) - handle_deregister_application (registry, message); + handle_disconnection (bus, registry, message); else res = DBUS_HANDLER_RESULT_NOT_YET_HANDLED; diff --git a/registryd/testregistry.py b/registryd/testregistry.py index 2bb684f..86be32a 100644 --- a/registryd/testregistry.py +++ b/registryd/testregistry.py @@ -9,18 +9,6 @@ from dbus.mainloop.glib import DBusGMainLoop DBusGMainLoop(set_as_default=True) -class Emitter (dbus.service.Object): - def __init__(self, bus, object_path): - dbus.service.Object.__init__(self, bus, object_path) - - @dbus.service.signal(dbus_interface='org.freedesktop.atspi.Tree', signature='s') - def registerApplication(self, app_name): - pass - - @dbus.service.signal(dbus_interface='org.freedesktop.atspi.Tree', signature='s') - def deregisterApplication(self, app_name): - pass - class IdleStateM (object): def __init__(self, bus, loop): self._bus = bus @@ -34,14 +22,15 @@ class IdleStateM (object): return True def setup(self): - self.emit = Emitter(self._bus, "/org/freedesktop/atspi/tree") - self.obj = self._bus.get_object("org.freedesktop.atspi.Registry", "/org/freedesktop/atspi/registry") + self.obj = self._bus.get_object("org.freedesktop.atspi.Registry", + "/org/freedesktop/atspi/registry", + introspect=False) self.itf = dbus.Interface(self.obj, dbus_interface="org.freedesktop.atspi.Registry") - return self.emit_registers + return self.register_apps - def emit_registers(self): - self.emit.registerApplication(":R123") - self.emit.registerApplication(":R456") + def register_apps(self): + #self.itf.registerApplication(":R456", ignore_reply=True) + #self.itf.registerApplication(":R123", ignore_reply=True) return self.print_applications def print_applications(self): diff --git a/tests/apps/test-application.c b/tests/apps/test-application.c index 550f810..487dd26 100644 --- a/tests/apps/test-application.c +++ b/tests/apps/test-application.c @@ -93,7 +93,7 @@ load_atspi_module(const char *path, int *argc, char **argv[]) bridge = g_module_open(path, G_MODULE_BIND_LOCAL|G_MODULE_BIND_LAZY); if (!bridge) - g_error("Couldn't load atk-bridge module : %s\n", path); + g_error("Couldn't load atk-bridge module : %s\n", g_module_error()); if (!g_module_symbol(bridge, "gtk_module_init", &init)) g_error("Couldn't load symbol \"gtk_module_init\"\n"); diff --git a/xml/org.freedesktop.atspi.Registry.xml b/xml/org.freedesktop.atspi.Registry.xml index 416a4f0..9abced1 100644 --- a/xml/org.freedesktop.atspi.Registry.xml +++ b/xml/org.freedesktop.atspi.Registry.xml @@ -9,11 +9,11 @@ interact with those applications.

The Registry service provides four basic functions to Assistive Technology (AT) clients: -

    -
  1. It provides a list of the applications who have registered with the - AT-SPI framework, thereby announcing their participation in the AT-SPI framework.
  2. -
  3. It gives access to system device events via the associated DeviceEventController interface.
  4. -
+
    +
  1. It provides a list of the applications who have registered with the + AT-SPI framework, thereby announcing their participation in the AT-SPI framework.
  2. +
  3. It gives access to system device events via the associated DeviceEventController interface.
  4. +

From the point of view of accessible applications (i.e. AT-SPI service producers), @@ -33,15 +33,53 @@ illustrating the relationship between applications, Registry, and AT is shown at: http://developer.gnome.org/projects/gap/tech-docs/SPIBlockDiagram.png

+ - Gets all the currently registered applications. + Gets all the currently registered applications. - - A list of strings containing the D-Bus bus names of the applications. - + + A list of strings containing the D-Bus bus names of the applications. + + + + + Updates an AT about recently added or removed applications. + + + + Unique bus name of the application that has been removed or added. + The integer is an enumeration: + 0 : The application has been removed. + 1 : The application has been added. + + + + + + + Register a new application with the accessibility registry. + + + + D-Bus Bus name of the application that wishes to be made accessible. + + + + + + + De-register an application from accessibility registry. + + + + D-Bus Bus name of the application that wishes to be made accessible. + + + + diff --git a/xml/org.freedesktop.atspi.Tree.xml b/xml/org.freedesktop.atspi.Tree.xml index b6746cc..23ddb35 100644 --- a/xml/org.freedesktop.atspi.Tree.xml +++ b/xml/org.freedesktop.atspi.Tree.xml @@ -105,25 +105,5 @@ - - - Register a new application with the accessibility registry. - - - - D-Bus Bus name of the application that wishes to be made accessible. - - - - - - De-register an application from accessibility registry. - - - - D-Bus Bus name of the application that wishes to be made accessible. - - -