GNOME Accessibility Logo

For Developers and Testers: This page provides information on the GNOME Accessibility architecture, developing accessible applications, and testing for accessibility.

A11Y-Love: Need help bringing many of these documents up to date.

A11Y-Love: Need to break these into categories, such as 'AT-SPI Infrastructure Overview', 'Designing for Accessibility', 'Developing for Accessibility', 'Testing For Accessibility', 'AT-SPI Implementation Best Practices'

Quick Notes on the Infrastructure Mechanics

Here's some quick notes on how the infrastructure starts and how applications connect to it.

Starting the Registry (gnome-session)

The AT-SPI registry is the core of the AT-SPI infrastructure. It is the means by which applications and assistive technologies can find and talk to each other.

gnome-session starts the at-spi-registryd, which lives in libexecdir (/usr/lib on Solaris) and also sets the GTK_MODULES environment variable to include gail and atk-bridge. Here's a quick layout of the relevant code in the gnome-session module:

The AT_SPI_IOR property is the way any client that has access to the X Windows display can find the AT-SPI registry. The AT-SPI registry is the way all assistive technologies can discover and interact with applications running on the desktop. The application that runs the AT-SPI registry is at-spi_registryd. Its source code lives in the registryd of the at-spi module. The relevant code that sets the AT_SPI_IOR property on the root window lives in registryd/registry-main.c:registry_set_ior.

See bug 163132 for complete details on the current implementation.

Autostarting Assistive Technologies

See the notes on how this is done via gnome-session. The nice thing is that gnome-session has been modified to stop using a special exec_ats property. Instead, it starts up assistive technologies via the same autostart mechanism used for all of GNOME (i.e., a *.desktop file under ~/.config/autostart), and the assistive technology setup (gnome-at-properties and gnome-default-applications-properties) ends up putting the correct *.desktop files in place. gnome-session-properties also provides some startup applications configuration. [WDW: I'm not quite sure how all these work together.]

How Applications Connect to the Registry

The GTK_MODULES environment variable specifies modules that GTK+ applications should load on startup. This is the hook for getting accessibility support into GTK+ applications -- when a GTK+ application runs, it will load the modules listed in GTK_MODULES. The most common setting for GTK_MODULES in an accessibility environment is:

GTK_MODULES=gail:atk-bridge

The gail module sets up the mapping of GTK+ widgets to atk widgets, and the atk-bridge module communicates with the at-spi-registryd that was started by gnome-session. The code that attempts to connect to the at-spi-registryd lives in the at-spi module under atk-bridge/bridge.c. It looks for the AT_SPI_IOR property on the root window to find the at-spi-registryd process and then attempts to connect to it.

At one time prior to the AT_SPI_IOR work, the at-spi-registryd would automagically (e.g., Bonobo activation) start if one attempted to tickle it and it wasn't running. Now, it needs to be explicitly started by gnome-session in order for the AT-SPI infrastructure to work.

How to issue events to reflect "focused" change

It is quite simple for us to notice what is going on when operating on the computer, but it may be a little challenging for a blind person to do so. As a result, we should provide feedback to these users by issuing events to Orca (a flexible accessibility application for people with visual impairments) to tell it what is going on. Specifically, to tell users which object is focused on the desktop, we need to issue "object:state-changed:focused" and "focus:" events to reflect the new object with focus.

The "object:state-changed:focused" Event

When to Emit "object:state-changed:focused" Event

When focus moves from one object to another, this event should be issued to reflect that the former object lost "focused" state and the latter one got it. Consequently, if there is a "focused" change, "object:state-changed:focused" event with regard to the above two objects will be emitted to specify the state change for both of them.

For example, if we press Arrow Right to move focus from one object (named "bin") to another ("boot"), Orca will receive the following events:

 object:state-changed:focused(0, 0, None)
        source: [icon | bin]
        application: [application | gtk-demo]
 object:state-changed:focused(1, 0, None)
        source: [icon | boot]
        application: [application | gtk-demo]

Where focused(0, 0, None) represents that "focused" state has been removed from "bin", while focused(1, 0, None) denotes that "focused" state has been added to "boot".

How to Emit "object:state-changed:focused" Event

To illustrate the process of emitting events, we continue to analyse the above example, pressing Arrow Right to move focus from one object ("bin") to another ("boot").

The "focus:" Event

When to Emit "focus:" Event

Let's take the above case as an example again, pressing Arrow Right to move focus from one object(named "bin") to another ("boot"). As the focus on the desktop has changed, it is reasonable to report this alteration to Orca. Consequently, "focus:" event as follows is needed to tell Orca which object is focused currently.

 focus:(0, 0, None)
       source: [icon | boot]
       application: [application | gtk-demo]

The above event denotes that the icon named "boot" is focused at present.

How to Emit "focus:" Event

There are several key functions to complete this process:

How to add children to GtkContainer

Quick Introduction to GtkContainer

A GTK+ user interface is constructed by nesting widgets inside widget. Container widgets are the inner nodes in the resulting tree of widgets: they contain other widgets. For example, you might have a GtkWindow containing a GtkButton containing a GtkLabel.

Abstractly, GtkContainer is a base class for widgets which contain other widgets. GtkBin, GtkBox, GtkTable, GtkList, GtkMenuShell... are all subclasses of the abstract GtkContainer base class. Generally, all the subclasses could be divided into two major kinds of container widgets in GTK+. The first type of container widget has a single child widget and derives from GtkBin, such as GtkButton, GtkFrame. The second type of container widget has more than one child, such as, GtkBox, GtkTable.

Anyway, all the container widgets are aimed to contain other widget. Consequently, the following will discuss how to add widgets to containers.

How to add a widget to containers

To demonstrate the process of adding a child to containers, we firstly take GtkBox as an example.

Example: GtkBox

GtkBox is a typical subclass of GtkContainer, which could contain more than one child. If we want to add a menubar to a GtkBox, the process is described as follows.

Accessibility/Developers (last edited 2008-08-18 07:08:38 by liyan.zhang)