contents last updated 1 June 2011
- 1 AT-SPI on D-Bus
- 2 AT-SPI D-Bus design
Introduction (skip to main contents)
AT-SPI technologies are currently migrating to D-Bus for their transport technology. As such, this document serves as a tutorial, design document and project update page for the
AT-SPI D-Bus project.
- Current Version:
- Previous Version:
Page Contributions: Instructions & Requirements
- Small factual errors or ambiguities should simply be updated with an improved wording.
- For open issues, marked with the string ToDo:, please add your name to comments. Such discussions should be replaced with an updated summary of the point once a conclusion has been reached to help readability.
- Please add a date wherever the information is subject to possible change in the future.
- Please update outdated content.
AT-SPI was originally designed for, and is currently implemented by the GNOME project using CORBA, an object-based IPC/RPC technology. CORBA is very portable but somewhat heavier weight than D-Bus.The
AT-SPI specification itself is tied to CORBA as it is defined in CORBA IDL. ORBit as an inter-process communication technology has many problems going forward, is deprecated in the Gnome project. CORBA does not exist in the KDE project and is generally resisted in embedded developments.
In an effort to move AT-SPI forward, a D-Bus project was started in November 2006. This took the form of a performance and design review available on the GNOME wiki. Work began on the implementation in May 2007.
Work is on-going and the project code is currently hosted at
git://git.gnome.org in the at-spi2-core, at-spi2-atk, and pyatspi2 modules.
AT-SPI D-Bus Design
AT-SPI consists of several parts:
The registry daemon has two distinct tasks.
- Keeping track of all the accessible applications on the desktop.
- Dealing with and forwarding X events over AT-SPI D-Bus.
The registry of accessible applications is relatively simple and has been fairly well tested.
- Possibly XEVIE code should be removed as this will not be available in future X.org releases.
A client side library in 'C' for access to AT-SPI accessibility information. Provides a wrapper around the D-Bus interface and also caches information when possible to avoid making round-trip D-Bus calls for commonly-accessed information that can easily be cached.
A Python wrapper around libatspi providing a more Pythonic AT-SPI interface that is compatible with the original CORBA-based pyatspi.
AT-SPI uses its own D-Bus bus, in order to handle accessibility of administrative applications. There is a program called at-spi-bus-launcher to manage the lifecycle of this bus and provide a method for retrieving its address.
Differences between AT-SPI D-Bus and AT-SPI CORBA
Remote reference counting is not implemented in AT-SPI2 for performance and complexity reasons There is a new caching mechanism where data accessed most often is transferred with accessible objects and will be cached by the AT-SPI bindings to avoid the need to make unnecessary round-trip calls. However, some widgets, such as Gtk treeviews and OpenOffice spreadsheets, may have numerous children that they create on an as-needed basis, so it would not be useful to enumerate them. These objects indicate this by setting the MANAGES_DESCENDANTS state. In the long term, we may want to change the way these objects are handled so that applications do not need to expose what could be an infinite space. However, it is important that existing applications continue to work without modifications, particularly applications not tied to GNOME, since they would otherwise need to act differently depending on which version of atk is present. The solution that we are using is for atk-bridge to 'lease' children of
ManagesDescendants objects; if these objects are not visible and are not accessed by a client for 30 seconds, then they may be garbage-collected. Wherever possible, including application events, synchronous method calls have been replaced by asynchronous D-Bus signals.
In other aspects the protocol is essentially the same as the current, IDL specified, at-spi interface. The two are intended to be completely compatible. This is so that API compatible bindings may be generated and ATs may be re-used with minor modification.
To be considered ready for testing in the open AT-SPI D-Bus must first pass the Orca test suite. Orca has the largest test suite of all accessibility applications and provides the best test for AT-SPI D-Bus. Previously AT-SPI D-Bus has performed very badly in these tests. Many of these failures may be performance related as the failures were different on lower specified PCs. Other failures are likely related to the caching used to improve performance. The caching means that if signals are missing to update accessibility values AT-SPI D-Bus will provide different data to the AT-SPI CORBA implementation.
Another test suite to consider would be the Mago test suite. This is a desktop testing suite for Ubuntu. It makes use of accessibility technologies and so would be a decent additional test for AT-SPI D-Bus.
D-Bus method calls are much slower than CORBA method calls, and this adversely affects AT-SPI. This is mitigated by client-side caching of the accessible hierarchy and basic object properties in AT-SPI2. Recent versions of AT-SPI2 are significantly morer performant than older AT-SPI2 versions due to the core being reimplemented in C and the use of direct D-Bus connections between ATs and applications. Still, it is possible that performance might differ widely for some tasks between AT-SPI1 and AT-SPI2.
The QtBridge used for making Qt apps accessible over AT-SPI D-Bus is being actively worked on but still needs work to be usable.
There is now a C-based AT-SPI binding, called libatspi. It is not compatible with the original CSPI library, so applications that used CSPI would need to be ported to the new library. For the medium term, a compatibility layer could be written to implement the old CSPI API on top of libatspi.
GAIL should be fixed to emit children-changed events when, ie, packing a box (http://bugzilla.gnome.org/show_bug.cgi?id=577392). Since at-spi2 caches children and states, a lack of events when these change will result in the cache not being updated.
On top of the test suites AT-SPI D-Bus needs more user testing before release.
Installation and Packaging
In the last AT-SPI D-Bus sprint, there were a number of options added for installing AT-SPI D-Bus at the same time as AT-SPI corba. These compile time options changed how the different parts of AT-SPI D-Bus were installed so that they could safely be installed on-top of a standard distribution that included AT-SPI CORBA. These options have not been documented meaning that it is not obvious how to install the AT-SPI D-Bus releases. These installation options need to be documented.
During the last sprint, a D-Bus bus was created specifically for accessibility. There is a script in Python that launches this bus. This was integrated with GNOME so that be bus would be launched on GNOME startup. This still needs some work. Currently the accessibility D-Bus bus does not participate in Gnome session management, which it should do. The registry daemon is launched automatically and does not necessarily need to participate with GNOME session management. Currently it does. The session management code will need moving to the D-Bus bus, but this will require that the Python wrapper is re-written in "C". This wrapper may be similar to the dbus-launch tool and could possibly be added to that.
Currently the releases are GNOME specific. Ideally it would be possible to use these releases with KDE.
AT-SPI D-Bus has been removed from the JHBuild system. It will need to be added back in for integration in to GNOME. TODO: Check this--I think that it is added in again. -MPG
The specifications for AT-SPI D-Bus have been specified in D-Bus XML with Qt extensions. This is because the Qt client bindings are the only ones that use it for automated code generation. Ideally the specifications would be written in such a way that other client or server side bindings could be generated using them.
Right now, the atk-bridge module is placed in the GTK+ modules directory. This was because at that moment, the main user of the atk-bridge were GTK+ applications, so place the module there made things easier. But atk-brigde is not a real GTK module. It doesn't have any GTK+ dependency. ATK is an abstract and toolkit independent API. Other toolkits has started to use it. As example Cally. In those cases, applications can't load the atk-bridge using the same GTK_MODULES approach, so (at this moment) it requires to load atk-bridge by hand. One of the main problems is locate where the module is. GTK+ knows were his modules would be placed, but this is not the case for other apps. atk-bridge should be located in a shared and common place, to be used for any toolkit (of course, no problem to keep atk-bridge on the gtk modules directory, to make easier their implementation). This problem was first mentioned the last August . At this moment GNOME Shell has solved it supposing a gconf variable with the
direction of the atk-bridge. GNOME-Shell bug . at-spi2 bug 
-  http://mail.gnome.org/archives/gnome-accessibility-list/2009-August/msg0...
-  https://bugzilla.gnome.org/show_bug.cgi?id=612599
-  https://bugs.freedesktop.org/show_bug.cgi?id=28580
AT-SPI D-Bus Specification
As well as the libraries using the AT-SPI D-Bus specification some work may still be required on the specification itself.
The D-Bus specification was originally written in Telepathy D-Bus XML, but the current code base has the Telepathy extensions removed. There is now a specification in an IDL-like language, but there are currently no tools to generate HTML documentation or C headers from this IDL.
- Either write scripts to convert the IDL into web-based documentation, or re-enable the Telepathy extensions and write an xst script to remove them in order to generate introspection data.
- Create new interfaces for management of large or infinite spaces.
Additional interfaces may be required for the management of accessible object life-cycle within infinite or very large containers. In the Bonobo / ORBit specification accessible objects were remotely reference counted and this was used as the method to manage their life-cycle within very large containers. Remote reference counting has been removed, meaning that new interfaces may be required.
The importance of this is possibly over-stated. Firefox exposes the entire DOM and does not have this problem. Open office exposes only the objects visible on-screen and therefore sidesteps this issue.
It is a requirement of the D-Bus AT-SPI system that applications running as other users, most importantly the root user, are made accessible on the desktop.
D-Bus does not have a multi-user bus, meaning some work will be required to make D-Bus AT-SPI work in the multi user case. D-Bus session busses are not, as sometimes imagined, per-X-session. The session bus is per-X-session, per-user. There has been some discussion about creating a "user bus" which may ultimately replace the current session bus. Such a user bus would likely meet the requirement of enabing accessibility of applications running as root in a user's session.
ATSPI D-Bus currently starts its own D-Bus daemon associated with the X session. This behavior could presumably be removed if the "user bus" is added into D-Bus.
This is the requirement to load a program remotely and have it accessible on the local desktop. The multi user work is a prerequisite for this. Possibly the best solution is to have an ICE transport for D-Bus.
There are three separate repositories for AT-SPI D-Bus. The 'Core' repository contains the D-Bus specification as well as the registry daemon and D-Bus helper libraries. The 'Atk' repository contains the AtkBridge library and the currently-broken cspi code, and the 'pyatspi2' repository contains pyatspi (the Python at-spi binding used by applications such as Accerciser and Orca).
The 'Core' repository can be downloaded by:
git clone git://git.gnome.org/at-spi2-core
The 'Atk' repository can be downloaded using git from:
git clone git://git.gnome.org/at-spi2-atk
The 'pyatspi2' repository can be downloaded using git from:
git clone git://git.gnome.org/pyatspi2
Libraries in the 'Atk' repository depend on the 'Core' libraries. The 'Core' software must be built and installed before attempting to build the 'Atk' libraries.
The libraries may generally be made using:
> ./autogen --prefix=prefix > make install
- The ATK Bridge will be loaded into every GTK application, possibly causing instability at this early stage.
Assume that when configuring the project:
libdir = /usr/local/lib pythondir = /usr/local/lib/python2.5/ libexecdir = /usr/local/libexec/
Then the registry daemon executable will be installed as:
The ATK Bridge library will be:
The registry daemon should be started automatically by the dbus daemon if atk-bridge or pyatspi request it.
> gcalctool --gtk-module=/usr/local/lib/gtk-2.0/modules/libatk-bridge.so & (Make an application accessible over D-Bus) > export PYTHONPATH=/usr/local/lib/python2.5/ (Ensure new pyatspi is found) > orca (Load an AT using pyatspi library)
dbus-monitor can be helpful for debugging AT-SPI. However, there are a couple of issues to be aware of. AT-SPI method calls are made over direct dbus connections when this is supported on the application side. This significantly improve performance, since messages no longer need to be routed through dbus-daemon, but it makes debugging with dbus-monitor more difficult. Direct dbus connections are enabled by default in at-spi2-atk when dbus-glib 0.90 or greater is available, but they can be disabled by passing --disable-p2p to configure. Libatspi will revert to using the dbus daemon if an application does not support direct connections (ie, if the call to GetApplicationBusAddress returns an error or an empty string). Additionally, when the accessibility bus is in use, it is necessary to point dbus-monitor to use it rather than the session bus. This can be done using a script such as the following:
dbus-monitor --address `xprop -root | grep AT_SPI_BUS | sed -e 's/.*= "//' | sed -e 's/"$//'`
It is possible to get Python backtraces using gdb. This can be useful when investigating crashes that happen within libatspi, for instance. For more information, visit http://wiki.python.org/moin/DebuggingWithGdb. It may help to rebuild python without optimizations (ie, CFLAGS=-g), since the symbols used by the gdb macros may otherwise be optimized out.
Due to its more aggressive use of caching, AT-SPI 2 is more sensitive to bugs in which toolkits fail to send events than AT-SPI 1. For AT-SPI 2.0.2 and later, there are methods to control the kinds of data that get cached (atspi_accessible_set_cache_mask for libatspi; setCacheMask for pyatspi). The following values can be specified:
- ATSPI_CACHE_NONE / pyatspi.cache.NONE
- ATSPI_CACHE_PARENT / pyatspi.cache.PARENT
- ATSPI_CACHE_CHILDREN | pyatspi.cache.CHILDREN
- ATSPI_CACHE_NAME | pyatspi.cache.NAME
- ATSPI_CACHE_DESCRIPTION | pyatspi.cache.DESCRIPTION
- ATSPI_CACHE_STATES | pyatspi.cache.STATES
- ATSPI_CACHE_ROLE | pyatspi.cache.ROLE
- ATSPI_CACHE_INTERFACES | pyatspi.cache.INTERFACES
- ATSPI_CACHE_ALL | pyatspi.cache.ALL
Note that these are bitflags and can be combined. Also, this method must be called on either the desktop (in which case it applies to all accessibles of all applications, unless it is overridden for an application) or an application's root accessible. Calling it on any other accessible has no effect. For instance, if an application has accessibles that can change their name without firing an event, then adding a line like the following into the application's Orca script's __init__ function might be useful:
Questions & Queries from Developers
- Andrés G. Aragoneses: Feedback from GNOME Hackfest 2008 (2008-10-17):
- One thing I learned in the summit as well is that there are still a bunch of important core parts of gnome that still use Bonobo (gconf for instance) even when there exist a dbus counterpart (gconf-dbus), which IIRC worked pretty well. Any insights about the reasons?
- Mark Doffman: Reply (2008-11-10)
- In the specific case of GConf there have been ongoing discussions about making wider ranging changes to the GConf library, and that this should go along with the D-Bus move. (See the DConf page). I haven't heard of any technical reasons why GConf has not moved to D-Bus. An implementation already exists and can be found on the Imendio page.
- Andrés G. Aragoneses: Feedback from GNOME Hackfest 2008 (2008-10-17):
- the vala&GObject-introspection topics where pretty interesting. I wonder if we should have used vala for at-spi-dbus (and prevent more memory leaks this way).
- Mark Doffman: Reply (2008-11-10)
- AT-SPI D-Bus could have used Vala for the ATK Bridge. This was initially adapted from the ORBit based 'C' version so a different programming language was not considered. The Vala D-Bus bindings are not completely stable, so extra work may have been required on the underlying tools.