Guidelines for Writing Accessible GNOME Applications Using GTK+ and the Accessibility Toolkit (ATK)

Version 1.0 August 2006 � Copyright IBM Corporation 2006

GNU Free Documentation License (GFDL)

Document Author/Editor:

Catherine Laws
IBM Software Group Accessibility Architecture and Development
e-mail

Most content derived from other documents and major contributions from:
Bill Haneman (Sun)
IBM Accessibility Architecture team (George Kraft, Pete Brunet, Larry Weiss, Aaron Leventhal, Richard Schwerdtfeger, Mark Pilgrim, Sueann Nichols, Donald B Clippingdale, Peter Parente)
Authors of the documents in the /References section.

Contents

  1. Guidelines for Writing Accessible GNOME Applications Using GTK+ and the Accessibility Toolkit (ATK)
    1. Abstract
    2. Notices
    3. Introduction
      1. Disability Needs
      2. Why use GTK+ and the ATK for Accessibility?
    4. Essential Accessibility Programming Practices
    5. GTK+ and ATK - A Foundation for GNOME Accessibility
      1. Why use GTK+ widgets?
        1. Creating accessible custom widgets
      2. Setting up the accessible application development and test environment
        1. Fedora extras and gnome-common
        2. libgail-gnome
        3. accerciser
        4. Orca screen reader
        5. Linux Screen Reader
        6. Glade GUI builder (optional)
    6. Using GTK+ and ATK to Build Accessible Applications
      1. Using the GTK+ Widgets Unmodified
      2. Exposing Accessible Information for Objects Embedded in GTK+ Text Widgets
      3. AttributeSets
      4. Changing Data Models and Cell Renderers
      5. ATK Implementations for GTK+ 2.0 Widgets
    7. The Accessible Toolkit (ATK) API Reference
    8. Building Custom Accessible Widgets
      1. Start with a GTK widget class
      2. Create and register an ''AtkObject'' factory
      3. Creating an ATK object implementation class
        1. Implement get_type plus class and instance initializer functions
        2. Implement base ''AtkObject'' methods and properties
        3. Implementing ATK Subinterfaces
      4. Managing Children
      5. Managing Events
      6. ATK implementation examples for documents
        1. Example: Paragraph with an Image in it
          1. HTML source
          2. Recommended ATK implementation
        2. Example: Header with a break in it
          1. HTML source
          2. Recommended ATK implementation
        3. Example: Link with a break in it
          1. HTML source
          2. Recommended ATK implementation
        4. Example: Two paragraphs with a horizontal line
          1. HTML source
          2. Recommended ATK implementation
        5. Example: Pagragraph with an emphasis
          1. HTML source
          2. Recommended ATK implementation
        6. Example: Paragraph with a link in it
          1. HTML source
          2. Recommended ATK implementation
        7. Link with an image in it
          1. HTML source
          2. Recommended ATK implementation
        8. Example: BLAH with a break in it
          1. HTML source
          2. Recommended ATK implementation
        9. Example: image map
          1. HTML source
          2. Recommended ATK implementation
        10. Example: bulleted list
          1. HTML source
          2. Recommended ATK implementation
        11. Example: numbered list
          1. HTML source
          2. Recommended ATK implementation
        12. Example: nested bulleted lists
          1. HTML source
          2. Recommended ATK implementation
        13. Example: form with a text area
          1. HTML source
          2. Recommended ATK implementation
        14. Example: form with checkbox
          1. HTML source
          2. Recommended ATK implementation
        15. Example: form with a selection
          1. HTML source
          2. Recommended ATK implementation
        16. Example: form with a multi line selection
          1. HTML source
          2. Recommended ATK implementation
    9. GNOME Development Tools
      1. Glade
        1. Keyboard equivalents, mnemonics for access keys, and accelerators
        2. Accessible names and descriptions
        3. Accessible relationships
      2. Accerciser
    10. Testing for Accessibility
      1. Accessibility testing checklist
    11. Documentation, Online Information and Help
      1. Accessible format for documentation
      2. Rationale
      3. Techniques
      4. Testing
      5. Documentation for accessibility features
      6. Rationale
      7. Techniques
      8. Testing
      9. Future Discussions
    12. Appendix
      1. Keyboard Bindings
      2. Reserved Key Mappings for Mobility Access Features
      3. Recommended ATK Implementations for Common UI Components
        1. Checkbox or Toggle Button
        2. Pushbutton
        3. Radio button
        4. Label or Static Text
        5. Combo box
        6. List box
      4. AT-SPI events
      5. Mapping MSAA and IAccessible2 to ATK
        1. Roles
        2. States
        3. Object Level Events aka Signals
        4. Relations
        5. Interfaces and Methods
          1. Creating accessible objects
          2. Base accessible interfaces
      6. Acknowledgments
        1. Review Team
      7. References
      8. Trademarks
      9. Technical support

Abstract

Application developers should consider the special needs of disabled users when they develop software programs for the Linux GNOME desktop. Meeting the needs of disabled users will benefit all users. In these guidelines, we discuss the following topics:

These topics are covered in detail with supporting rationale, citing specific GTK+ and ATK interfaces. Examples are provided where appropriate.

These guidelines highlight the GNOME accessibility features and provide guidance for creating accessible Linux GNOME software. To print the guidelines document it is best to print all linked documents. The latest version of this document, as well as additional accessibility resource information, can be found in the Accessibility References section of this document.

Notices

THIS DOCUMENT IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.

All statements regarding future intent are subject to change or withdrawal without notice and represent goals and objectives only.

Information in this document about non-IBM products was obtained from the suppliers of those products, published announcement material, or other publicly available sources.

The information contained in this document represents the current views of IBM on the issues discussed as of the date of publication. IBM cannot guarantee the accuracy of any information after the date of publication.

Introduction

When writing a GTK+ application, think about the fact that users with varying abilities will want to use the application. Some users with mobility impairments cannot use their hands for traditional mouse and keyboard input; other users who are blind may not be able to use a mouse, see the screen, or read a printed User's Guide.

Over the years, disabled users and Assistive Technology Vendors (ATVs) have invented incredibly clever work-arounds for these problems. Voice input replaced the mouse, mouth sticks and switches replaced the keyboard, text-to-speech synthesis replaced the screen, and online books replaced printed books.

Some products include unintentional roadblocks to people who have disabilities. Some examples:

  • Programs that provide mouse only input are inaccessible for use by people who are blind or who have mobility impairments and require alternative inputs, such as input using voice recognition. In addition, programs with mouse only input may not be adaptable to devices which do not have a mouse.
  • Programs that use audio-only messages (individuals who are deaf cannot hear the messages - this also applies to people with systems that do not have sound capability).
  • Operating systems that define Ctrl+Alt+Del to reboot the system (try doing this with only one hand).

The following section discusses disability issues. Understanding these issues enables better understanding of how to create an accessible GTK+ solution.

Disability Needs

The following describes what disabled users need:

Users who are blind or who have low vision need:

  • Keyboard alternatives to the mouse (mouseless operation).
  • Text descriptions of graphics (such as short alternative or title text, and longer descriptions for complex graphics like tables).
  • Text description of video and/or a descriptive audio track.
  • To know which object has focus and when the focus changes.
  • To know the default action and how to take that action.
  • Online documentation.
  • Screen magnification.
  • High color contrast.

Users who are deaf or hard of hearing need:

  • A visual indication of any sound.
  • Text captioning of multimedia presentations.
  • Text description of significant audio.

Users who are mobility impaired need:

  • Voice or assistive device input
  • Equivalent keyboard support for mouse input
  • Modified keyboard response (sticky keys, bounce keys, repeat keys)
  • Alternatives to multiple key inputs.
  • Online documentation.

Users who have multiple disabilities need:

  • Combinations of solutions; for example, speech output and voice input that do not conflict.

However an application developer doesn't have to provide all of the solution. Enable an application so that assistive technology (AT) programmers can obtain from the application program what it needs to present to it's users.

Why use GTK+ and the ATK for Accessibility?

GTK+ is the GNU Image Manipulation (GIMP) Toolkit, which is is a multi-platform toolkit for creating graphical user interfaces. GTK+ is based on 4 libraries: the GLib core library, GTK object library, Pango for layout and rendering, and the Accessibility Toolkit (ATK). Many of the ATK accessibility interfaces were derived from the Java accessibility API, which was developed by software accessibility engineers at Sun and IBM. ATK describes a set of interfaces that GUI components in applications need to implement to be accessible. The interfaces are toolkit-independent, meaning that the implementations could be written for any widget set, such as GTK, Motif or Qt, but this document will focus on ATK with the GTK widget set. Widgets are user interface objects like buttons, menus, dialog boxes, text entry fields, combo boxes, etc. The GTK+ libraries are like the Active Template Library (ATL) on the Microsoft Platform, which provides a ready-made framework for creating Component Object Model (COM) Objects and Components (ActiveX EXEs and ActiveX DLLs).

The accessibility enablement of an application is easier if the GTK+ accessibility features are exploited during development. First, minimal development resource is required to incorporate the accessibility features of GTK+ widgets. Second, software will be universally accessible for all users. Third, features specifically designed for disabled users often make the product more usable for non-disabled users as well. For example, a "keyboard-enabled" application improves usability for blind users who use a screen reader as well as for people who use voice recognition software.

GAPArchitecture3.jpg

Assistive Technology Vendors (ATVs) benefit as well. If an application implements GTK+ accessibility features, ATVs, such as screen reader vendors, can more easily make their products work with that accessible GTK+ application. Screen reader software receives information from running GTK+ applications using AT-SPI(Assistive Technology Service Provider Interface). Accessibility support for applications is "built in" to application toolkits via toolkit-appropriate APIs. For instance, ATK is the accessibility toolkit for most native C applications, and the Java Accessibility API is the toolkit for Java applications. These application accessibility APIs are then exported to the common AT-SPI interface via the relevant "bridge" (see the diagram above) of the GNOME Accessibility Platform (GAP).

Look for the ATK API library in the atk module in GNOME CVS. Because support for the accessibility API is built into the GTK widgets used by GNOME, a GNOME program should function reasonably well with assistive technologies with no extra work. For example, ATVs can automatically read the widget labels that are normally set in an application with GTK function calls such as gtk_label_set_text() or gtk_button_new_with_label()). They can also find out if there is any tooltip text associated with a widget, and use that to describe the widget to the user.

The accessibility API for GTK widgets is implemented in the GAIL (GNOME Accessbility Implementation Library) module, which a GTK application can dynamically load at runtime. Once GAIL is loaded, application components which use standard GTK widgets have a basic level of accessibility without modification. If GAIL is not loaded, GTK widgets and applications are not considered accessible. Whether or not GNOME/GTK+ applications automatically load these accessibility support libraries depends on the value of the accessibility gconf key named "/desktop/gnome/interface/accessibility". A boolean value of "true" enables support for assistive technologies. To enable GNOME accessibility features by setting the accessibility gconf key, type the following command line:

gconftool-2 --type bool --set /desktop/gnome/interface/accessibility true

If an application calls gnome_program_init, it will automatically load the appropriate accessibility libraries at runtime, but that application will be limited to running on the GNOME desktop. "Pure GTK+ applications" (those that use gtk+ but do not link to libgnome) require the user (or the application?) to set the value of the GTK_MODULES environment variable to "gail:atk-bridge" to enable assistive technology support. GTK_MODULES cause libgail.so and libatk-bridge.so to be loaded. Pure GTK+ applications could potentially run on other UNIX desktops that support ATK, such as KDE.

A GTK+ widget is accessible if it follows the guidelines found in Using GTK+ and ATK to Build Accessible Applications. ATK implementations are provided for the "stock" GTK+ widgets. In many cases new widgets which derive from existing GTK+ widgets will also inherit suitable accessibility support.

Though GTK+ widget's built-in accessibility support provides significant functionality without any accessibility-specific code changes on the part of the application, application developers can often improve on the accessible information provided for some of the widgets, and tailor it to that widget's specific purpose in an application, via straightforward calls to ATK methods in the application. For instance, in most cases developers should add or change the textual names and descriptions, add mnemonic keyboard bindings to labels, and associate labels for these widgets with the appropriate ATK function call, so that an assisitive technology can describe their purpose or state, key bindings, and labels to the user.

Essential Accessibility Programming Practices

The IBM accessibility developer guidelines provide an excellent set of essential accessibility programming practices plus other references for software applications in general, Web documents and applications, Java and Eclipse-based applications, IBM Lotus Notes�, hardware, and documentation in general.

Also reference the user interface accessibility guidelines from the GNOME Accessibility for Developers guide.

GTK+ and ATK - A Foundation for GNOME Accessibility

GTK+AppArchitecture.jpg

FIGURE 1.0 GTK+ Accessible Application Architecture

The GTK+ accessibility architecture depends on a number of libraries and interfaces for programming a GTK+ application, and for making the objects and interfaces accessible, translatable, and usable:

  1. TheGLib library provides portability and convenience functions, generic data structures, and the GLib main loop.

  2. The GDK library provides an abstraction layer between the GTK+ widgets in an application and the underlying X window system.

  3. The GTK+ Object System provides a library and class hierarchy of objects (including widgets, containers, windows) with features that include inheritance, polymorphism and reference counting, signal notification, and attributes.

    • Drag and drop interfaces support the Motif or Xdnd Drag and Drop protocols.

    • User-interface customization is accomplished using themes. Without recompiling either GTK+ or the application, users can choose a new look for their applications by installing a new theme. A theme can either be simply a set of colors and pixmaps used by the existing drawing code or it can be a complete replacement of the functions used to draw widgets. Themes are useful for low vision users.

  4. The Pango engine and library provides functions for text layout and rendering, with internationalization considerations.

  5. The ATK library provides all the accessible object classes (based on GObject) and the interfaces the accessible objects implement (based on GInterface).

  6. ATK is an in-process accessibility API, written to by applications and implemented for GTK+ widgets by GAIL (GNOME Accessbility Implementation Library), which a GTK application dynamically loads at runtime if the value of the accessibility gconf key (/desktop/gnome/interface/accessibility) is "true."

  7. AT-SPI is an out-of-process CORBA API implementation used by assistive technologies. The ATK bridge exports ATK to AT-SPI for GTK+ applications.

Why use GTK+ widgets?

When using the GTK+ widget set, most accessibility information is built into the widgets by GAIL except for doing the following:

  • Provide names and descriptions of some controls and images using atk_object_set_name and atk_object_set_description() or atk_image_set_description().
  • Specify relationships between labels and controls and between groups of controls using atk_relation_new() and atk_relation_set_add(). Note that GAIL does automatically create RELATION_LABELLED_BY/RELATION_LABEL_FOR labels and widgets which are attached next to one another in table layouts.
  • Define access key mnemonics for controls using GTK methods such as gtk_radio_button_new_with_mnemonic. For controls which have separate labels (like text boxes, combo boxes, sliders, sping buttons, etc), use GTK methods to set the mnemonic on the label (gtk_label_new_with_mnemonic) and to associate the mnemonic access key with its control (gtk_label_set_mnemonic_widget).
  • For commonly used functions in menus, define accelerators, or shortcut keys, using the GtkAccelLabel and GtkAccelGroup interfaces plus the methods gtk_window_add_accel_group and gtk_widget_add_accelerator.

ATKObjectArchitecture.jpg

Figure 1.1 Accessible Component Architecture for GTK+ Object

Creating accessible custom widgets

While many applications for Linux may not use GTK+ widgets, the discussion of how to make GTK+ widgets accessible using ATK interfaces and Atk#ATKIFORGTK how GAIL implements ATK for GTK+ widgets] provides us with a model for implementing ATK interfaces (methods, attributes, signals, etc) to make custom widgets in Linux GNOME applications accessible.

Since ATK uses the standard GObject and GType model, take advantage of inheritance by creating custom widgets. Implement ATK objects and interfaces for widgets either directly in a custom ATK implementation library, in the application itself, or in an external implementation library, like the GAIL library. For example, create an AtkObject subclass which can inherit from the "default" GAIL ATK implementation, override selected ATK methods, support selected ATK interfaces, and use GAIL utilities such as AtkText helpers for Pango classes. Custom widgets should fire appropriate ATK events, such as focus and property changes. To associate a widget's ATKObject subtype, override get_accessible for the GtkWidgetClass OR associate an AtkObjectFactory with the AtkRegistry. All the application ATK interface, object, and event information is exported through the ATK bridge to the AT-SPI interface for use by assistive technologies like the Orca and Gnopernicus screen readers.

To build an accessible application with the least amount of effort do the following:

  1. Wherever possible, use GTK+ widgets to build an application, as described in Atk section 4.0 Using GTK+ and ATK to Build Accessible Applications].

  2. If the rich class library in GTK+ does not have a desired widget, create a custom widget by subclassing the AtkObject class. Implement the Accessibility API for a widget as described in Custom section 5.0 Building Custom Accessible Widgets].

  3. If steps 1 and 2 are not sufficient, implement the Accessibility API for a class library or widget as described in AtkApi section 6.0 The Accessibility API]

Making GNOME Applications Accessible by Marc Mulcahy and Bill Haneman from Sun provides a good overview of using ATK, GTK+, and Glade to make both standard and custom widgets accessible in an application.

A custom ATK implementation is the Mozilla ATK Implementation (MAI), which exposes its nsIAccessible and nsIAcc extensions through ATK objects and interfaces. When accessible events that need to be reported are generated in Mozilla, MAI creates the proper ATK objects and sends ATK signals for those events. When Mozilla receives accessible commands from AT-SPI through the ATK interface, MAI sends the commands to Mozilla though nsIAccessible and nsIAcc extensions.

Eclipse developers use SWT widget accessibility interfaces (org.eclipse.swt.accessibility) to enable custom SWT widgets. Eclipse then exposes both standard and custom accessible SWT widgets as accessible GTK+ widgets by implementing ATK objects and interfaces for the SWT widgets. Especially look at chapters 4, 9, and 13 to understand SWT accessibility interfaces, how they relate to ATK objects, and how to enable accessibility for custom SWT widgets.

Note: Externally refer to Creating accessible applications with Eclipse: An Introduction.

CKL: The SWT widget set and the Eclipse accessibility interface needs to be enhanced to support more of the ATK interfaces related to relationships, tables, images, hypertext, hyperlinks, etc.


Currently, the UNO Accessibility API for OpenOffice and StarOffice is wrapped by the Java Accessibility API and is exported through the GNOME Java Access Bridge to AT-SPI. Work is in progress by Novell to map the OpenOffice/StarOffice UNO Accessibility API directly to ATK, and to go through the ATK bridge to AT-SPI.

Setting up the accessible application development and test environment

To set up an environment for developing and testing accessible GTK+ applications on Fedora Core 6, download and install the following packages.

  1. Fedora extras
  2. gnome-common
  3. libgail-gnome
  4. accerciser
  5. Orca or LSR screen reader
  6. Glade GUI builder (optional)

Accessibility in GNOME is disabled by default. Before running any accessibility tools or accessible applications:

  1. Set the value of the GTK_MODULES environment variable to "gail:atk-bridge". GTK_MODULES cause libgail.so and libatk-bridge.so to be loaded. (Note: For GNOME applications, this step is not necessary but for GTK+ applications, it is. Add the following code to the beginning of applications to setup the accessibility environment. Also, add the following to the compile linker line "-lgnome-2 -lgnomeui-2".:
              gnome_program_init(
    
                             "dialog", "0.1",
    
                             libgnomeui_module_info_get(),
    
                                     argc, argv,
    
                             "app-datadir",
    
                                     "/usr/local/share",
    
                             NULL);
    
  2. Enable accessibility by doing one of the following:
    1. Run "gconftool-2 -s -t boolean /desktop/gnome/interface/accessibility true" (preferred method)
    2. Include "GNOME_ACCESSIBILITY=1" in the user profile file (deprecated)
    3. Select Desktop -> Preferences -> Accessibility -> Assistive Technology Support. Check the Enable assistive technology box.

After enabling accessibility, run an application from the command prompt and the following messages should be displayed:

Bonobo accessibility support initialized

GTK Accessibility Module initialized

ATK Accessibility Bridge initialized

Fedora extras and gnome-common

Install the gnome-common package, but first setup Fedora Extras:

su - root

rpm --import http://download.fedora.redhat.com/pub/fedora/linux/extras/RPM-GPG-KEY-Fedora-Extras

# missing step to create /etc/yum.repos.d/fedora-extras.repo

yum install gnome-common

libgail-gnome

Fedora does not provide the libgail-gnome.pc package configuration file required to build and run accerciser, so build and install it manually:

su - root

cd /usr/tmp

cvs -d:pserver:anonymous@anoncvs.gnome.org:/cvs/gnome checkout libgail-gnome

cd libgail-gnome

./autogen.sh

make

install -m 444 libgail-gnome.pc /usr/lib/pkgconfig

accerciser

Build and install Accerciser:

su - root

cd /usr/local/src

svn checkout http://svn.gnome.org/svn/accerciser/trunk/ accerciser

cd accerciser

./autogen.sh

make

make install

Orca screen reader

In addition to installing Fedora extras and gnome-common, install pyorbit-devel.

yum install pyorbit-devel

Then build and install Orca:

su - root

cd /usr/local/src

svn checkout http://svn.gnome.org/svn/orca/trunk/ orca

cd orca

./autogen.sh

make

make install

Next look in the following directories: <What are we looking for?>

/usr/local/bin/orca*

/usr/local/lib/python2.3/site-packages/orca

/var/tmp/orca

Run orca-setup once.

export PYTHONPATH=/usr/local/lib/python2.3/site-packages/orca:/usr/lib/python2.3/distutils

orca-setup

This is how to run Orca:

FIXME: need help filling this section out. is this information complete?

export PYTHONPATH=/usr/local/lib/python2.3/site-packages/orca:/usr/lib/python2.3/distutils

orca

Linux Screen Reader

To build and install LSR:

su - root

cd /usr/local/src

svn checkout http://svn.gnome.org/svn/lsr/trunk/ lsr

cd lsr

./autogen.sh

make

make install

Glade GUI builder (optional)

Refer to the Glade CVS README for requirements and instructions about installing Glade on a system.

Using GTK+ and ATK to Build Accessible Applications

This section discusses how to use GTK+ widgets and ATK to build an accessible GTK+ application:

Using the GTK+ Widgets Unmodified

The GTK+ is an extremely rich class library that has implemented keyboard accessibility, as well as the accessibility API (ATK) is implemented by the GNOME Accessibility Implementation Library (GAIL)for each GTK+ widget. (Note: If developing proprietary code, do not review GAIL or any other open source code protected by open source licenses. Violating this rule could compromise the originality of proprietary code.) If using GTK+ "as is", do the following:

  1. Set the accessible name on all GTK+ widgets that are rendered on the screen

    For interactive widgets, the accessible name should match the visible text label associated with the widget, if there is one. If not, the name should be the implied label for the widget, such as "Search" for a search text entry field. For images and icons, the name should be a short title, alternative text, or caption that identifies the image. Provide a name for both interactive and non-interactive images and icons using atk_object_set_name.

    C example:

      {
    
         AtkObject *obj;
    
         obj = gtk_widget_get_accessible (save_button);
    
         atk_object_set_name (obj, _("Save"));
    
      }
  2. Provide descriptive text for all images and icons, and for interactive widgets that have tool tip or contextual help: Some GTK+ widgets provide default descriptions, but in some cases these descriptions should be more meaningful. Even if tool tips are added to GTK+ widgets, this text may not be accessible to an AT without providing the accessible description. Use atk_object_set_description to provide accessible, meaningful descriptions that match tool tip or contextual help for interactive widgets. C example:

      {
    
         AtkObject *obj;
    
         obj = gtk_widget_get_accessible (save_button);
    
         atk_object_set_description (obj, _("Saves all the settings and dismisses the dialog."));
    
      }

    In addition, provide descriptive text for all important images and icons that convey meaning to the user, including icons (like GtkStatusIcon), buttons with icons (like GtkButton, GtkColorButton, GtkArrow)), toolbar elements (GtkToolButton), images that are pictures (GtkImage), and images that are inserted into text (using GtkTextBuffer) or table cells (GtkCellRendererPixbuf). Use atk_image_set_description to specify meaningful descriptions for these images. C example:

      {
    
         AtkObject *obj;
    
         obj = gtk_widget_get_accessible (file_save_icon);
    
         atk_image_set_description (obj, _("Saves this document as a file."));
    
      }
    
    • Python example to set both accessible name and descriptive text:

      import gtk
    
      def setNameDesc(widget, name=None, description=None):
    
        '''
    
        Sets the name, and description (optional), of a GTK+ widget.  Example code:
    
          setNameDesc(apply_button, 'Apply')
    
          setNameDesc(up_button, 'Up', 'Move the selected item up")    
    
        '''
    
        acc = widget.get_accessible()
    
        if name is not None:
    
          acc.set_name(name)  # widget.set_name() is not sufficient
    
        if description is not None:
    
          acc.set_description(description)
    
  3. Label widgets by establishing a relationship

    When a GtkLabel is used to label another widget control, from the label widget, use atk_relation_new to specify the ATK_RELATION_LABEL_FOR type and point to the associated widget control. From the widget control, use atk_relation_new to specify the ATK_RELATION_LABELLED_BY type and point to the associated label widget. Then use atk_relation_set_add to add both relationships.

    C example:

      {
    
              GtkWidget *widget;
    
              GtkLabel *label;
    
              AtkObject *atk_widget, *atk_label;
    
              AtkRelationSet *relation_set;
    
              AtkRelation *relation;
    
              AtkObject *targets[1];
    
              atk_widget = gtk_widget_get_accessible (widget);
    
              atk_label = gtk_widget_get_accessible (GTK_WIDGET (label));
    
              relation_set = atk_object_ref_relation_set (atk_label);
    
              targets[0] = atk_widget;
    
              relation = atk_relation_new (targets, 1, ATK_RELATION_LABEL_FOR);
    
              atk_relation_set_add (relation_set, relation);
    
              g_object_unref (G_OBJECT (relation));
    
              relation_set = atk_object_ref_relation_set (atk_widget);
    
              targets[0] = atk_label;
    
              relation = atk_relation_new (targets, 1, ATK_RELATION_LABELLED_BY);
    
              atk_relation_set_add (relation_set, relation);
    
              g_object_unref (G_OBJECT (relation));
    
      }
    
    • Python example:

      import gtk, atk
    
      def setRelation(source, atk_relation, *targets):
    
        '''
    
        Sets the relation between a GTK+ source widget and one or more GTK+ target
    
        widgets. Example code:
    
          import atk, pyatk
    
          pyatk.setRelation(item, atk.RELATION_LABELLED_BY, item_label)
    
          pyatk.setRelation(group_label, atk.RELATION_LABEL_FOR, member1, member2)
    
          pyatk.setRelation(spinner_button, atk.RELATION_CONTROLLER_FOR, spinner)
    
        For a list and definition of ATK relationships, see: 
    
        http://developer.gnome.org/doc/API/2.0/atk/AtkRelation.html    
    
        '''
    
        acc_targets = [] # list of accessible widgets to apply relation attribute
    
        acc_src = source.get_accessible()
    
        relation_set = acc_src.ref_relation_set()
    
        # get a reference to each widget and add to the accessible target list
    
        for target in targets: 
    
          acc_targ = target.get_accessible()
    
          acc_targets.append(acc_targ)
    
        relation = atk.Relation(acc_targets, 1) # create the relation
    
        relation.set_property('relation-type', atk_relation)
    
        relation_set.add(relation) # apply the relation to the target widget(s)
  4. Enable keyboard access

    Default keyboard navigation, such as moving focus between interactive widgets using the Tab key, has built-in accessibility. If keyboard access features, such as mnemonics and accelerators, are added to widgets, GAIL implements the AtkAction interface and the atk_action_get_keybinding method for a widget if the following is done:

    • If the mnemonic is in a label (GtkLabel) that is separate from its control (like GtkSpinButton, GtkHScale, GtkEntry, GtkComboBox, etc.), use gtk_label_set_mnemonic_widget to associate the mnemonic access key with its control and to cause focus to move to the control when the mnemonic key indicated in the label is pressed.

    • To add accelerator or shortcut keys to widgets like GtkMenuItem, use the GtkAccelLabel and GtkAccelGroup interfaces along with the gtk_window_add_accel_group, gtk_widget_add_accelerator, and gtk_menu_item_new_with_label methods.


  5. Group objects that go together inside named frames or notebook pages

    Logically group widgets that go together and assign that grouping a name. This facilitates navigation of an application. Two ways to do this include adding widgets to a GtkFrame (which is like a group box) or on pages of a GtkNotebook. Use atk_object_set_name to set the accessible name to the tab label for each page in a notebook, and to the frame label for a frame (group box). Use atk_relation_new and atk_relation_set_add to establish a relationship of ATK_RELATION_MEMBER_OF between the group (frame or notebook object) and each widget in the grouping.

  6. Make sure some widget has the focus at all times

    Make sure some widget in the application has the input focus at all times. When keyboard enabling an application, this should take care of itself. Most of the GTK+ widgets implement focus setting to support keyboard navigation. See Essential#_Toc412398974 section 2.3 Providing Focus] for additional information on setting the focus.

  7. Provide an accessible layout that yields a logical focus tab order

    When developing the visual layout of widgets, provide a logical layout which is determined by the order in which widgets are added in the source code. GTK+ layout containers help developers add widgets to an application in a logical order that matches the visual layout. The logical layout affects the keyboard tabbing sequence and the order an assistive technology uses to read an application. GTK+ automatically computes the focus tab order for widgets based on the order in which they are defined in the source code. If the focus tab order is changed by using gtk_container_set_focus_chain, for example, then the tab order may become confusing for users because it is not predictable. Usually it is better to change the visual layout to produce the desired logical layout than to change the focus chain.

  8. Show relationships when one widget controls another

    When the state of one widget, like a radio button, controls something about another widget, such as whether or not the widget is enabled or displayed, then use the ATK_RELATION_CONTROLLED_BY and ATK_RELATION_CONTROLLER_FOR relationships.

  9. Show relationships when one widget embeds another one

    When one widget, like an image, is embedded into another widget, like a text buffer, use the ATK_RELATION_EMBEDDED_BY and ATK_RELATION_EMBEDS relationships.

  10. Other relationships to point out? (http://developer.gnome.org/doc/API/2.0/atk/AtkRelation.html)

  11. Specify caption and summary for data tables and establish table cell and header relationships

    Identify the caption for a data table, describe the purpose of the table in a summary, describe rows and columns, and show the relationship between table cells and row/column headers using the following ATK methods:

      atk_table_set_caption
    
      atk_table_set_summary 
    
      atk_table_set_row_description
    
      atk_table_set_column_description 
    
      atk_table_set_row_header
    
      atk_table_set_column_header
  12. Add descriptions for the actions of interactive widgets

    Use atk_action_set_description to describe the results of the actions of interactive widgets.

    C example:

      {
    
      atko = gtk_widget_get_accessible (play_button);               
    
      AtkAction *action = atk_object_get_action (atko, 0);
    
      atk_action_set_description (action, _("Plays the selected audio file."));
    
      }

Exposing Accessible Information for Objects Embedded in GTK+ Text Widgets

GtkTextBuffer and GtkTextView are classes that allow the creation of a document object model. Text in a buffer can be marked with tags (GtkTextTag), which are attributes that can be applied to some range of text. However, tags can affect more than appearance; for example, they can affect the behavior of mouse and key presses or "lock" a range of text so the user can't edit it. Positions in the text buffer can be remembered or "marked" using the GtkTextMark widget, and images can be inserted into the text buffer as one character GDKPixbuf objects. Child widgets, like links and other control widgets, can be "anchored", or inserted inline as if they were characters, in the text buffer as GtkTextChildAnchor objects. The anchor can have multiple widgets anchored allowing for multiple views.

What enables assistive technologies, such as a screen reader, to obtain the accessible information and events for objects embedded in text widgets, which can be anything from a simple single line entry field to a complex document, are the implementation and maintenance of the methods, attributes, and signals in the following ATK interfaces:

  • AtkObject class to expose basic accessibility information (e.g. name, description, role, states, value) for the text buffer and view objects and all of its child objects (paragraphs, images, links, controls, etc). Note: Additional roles and states for document objects are being added.

  • AtkDocument interface, if the text widget is viewed as a document, to indicate the document boundaries in the accessibility hierarchy, the locale, and document attributes and to expose document events. Note: The AtkDocument interface is in the process of being updated.

  • AtkText interface for the text buffer and each text object in the buffer that is not editable to expose text attributes, caret position, selection, and text events, such as when the caret moves or the text or text attributes change. For text objects in the text buffer which are editable, the AtkEditableText interface should be implemented instead.

  • AtkHypertext interface to identify all embedded objects, including both text and image links, non-link images, form controls, plug-in objects, etc. All interactive objects, such as links and form controls, must also implement AtkAction to identify actions and key-bindings. The AtkRelations interface should also be implemented to indicate relationships between the text buffer and the embedded objects as well as between other objects, such as between labels and form controls.

  • AtkHyperlink object interface to identify all links or sets of links in a hypertext document and their link attributes, like the URI. AtkHyperlink objects must also implement the AtkAction interface to identify actions and key-bindings. <I don't think form controls implement AtkHyperlink, do they?>

  • AtkImage interface for images embedded in the text buffer to expose image descriptions, size, and location.

  • AtkTable interface for objects which need to expose row/column information (headers) and other tabular information (captions, summaries, etc), such as data tables, calendars, and spreadsheet-like widgets.

  • AtkSelection interface for the text buffer and all embedded object containers (like a table?) in the buffer if there are child objects which can be selected. Note that selection of text and other objects that are not children is done using other interfaces that have selection methods, such as AtkText.

For more information, refer to the ATK Reference, AT-SPI interface descriptions, and the Custom Building Custom Accessible Widgets] section in this guide.

AttributeSets

An AttributeSet is a list of name-value pairs, returned as a sequence of strings; the name and value are separated by a colon. There are several different types of AttributeSets, some with pre-defined (enumerated) name-value pairs, and some to which custom name-value pairs can be added if needed:

  1. AtkObject AttributeSets. The attributes in this set may be considered weakly-typed, general properties or annotations which are not specific to visual text objects and cannot be applied to a specific range of characters being displayed. These attributes are not the same as the strongly-typed interface instance data attributes declared using the IDL "attribute" keyword. For example, attributes of Accessible objects which correspond to XHTML content elements should have attribute names and values which match those specified in the W3C XHTML specification, where such values are not already exposed as pre-defined ATK roles, objects, or interfaces. For example, "xhtml:navbar" could be used to expose a section of a document object that is a navigation bar.

  2. AtkDocument AttributeSets. These attributes are specified for a document as a whole, such as "docurl:http://www.ibm.com" to specify the URI for an HTML document.

  3. AtkText AttributeSets. These attributes are formatting, typographic, or semantic attributes or qualitites which apply to a range of text specified by starting and ending offsets. There are many text attributes defined in the ''AtkTextAttribute'' enumerations, but add more as needed. For example, add "abbr:International Business Machines" to expose the title attribute value for an abbreviation tag in an HTML document.

Whenever possible, use pre-defined attributes and ATK objects and interfaces to identify the objects in text and document objects. Assistive technologies may not know how to handle an object with a custom attribute defined by an application. In addition to checking the text attribute enumerations, make sure to check for pre-defined ATK roles or interfaces that could be implemented to define and expose the accessible information for a custom object. For example, to specify the title of a document, use atk_object_set_name instead of defining a custom document attribute.

Changing Data Models and Cell Renderers

<I'm not sure if this section is completely accurate. It's a mixture of what was said in the Java article and what is said in the GTK reference manual about cell renderers. But I don't see anything about cell renderers related to GtkTables, so there is only info about GtkTreeView cell renderers. >

The root component class is called GObject. The design of each component is based on the Model-View-Controller (MVC) architecture. Each component is broken into three parts:

  • Model or "data" portion of the component.
  • User Interface or "look and feel" portion, also called the view.
  • Controller portion, which manipulates the components.

Implementation of the Accessibility API is triggered from the "data portion" of each GTK component. This allows implementation of an accessible application without affecting its "look and feel."

When developing an application using GTK, it is important to avoid modifying or replacing the "data model portion" of each component with a custom one. Otherwise, there is risk of improper implementation of methods that are required to support the interfaces and the breaking of the accessibility features of the component.

Another GTK concept is a cell renderer, which is an object primarily used to draw certain graphical elements within a list of elements. For example, GtkTreeView widgets use GtkCellRenderer to draw many cells on the screen.

If changing the cell renderer for a GTK object, make sure it implements AtkObject. If implementing a cell renderer on an existing GTK object, configure the cell renderer for the given element and reuse an already accessible component.

ATK Implementations for GTK+ 2.0 Widgets

The following table lists GTK+ 2.0 user interface widgets with their ATK role and interface implementations in GAIL. If an interface or role is not listed, either the widget does not support that interface or it inherits its implementation of that interface or role from an ancestor widget indicated by the GAIL Inheritance column.

Note: Deprecated GTK+ widgets were not included in this table even though some of them have GAIL implementations (such as GtkCList, GtkCombo, GtkList, GtkPixmap, and GtkOptionMenu). Also note the application programmer needs to make embedded objects and document structure accessible in the GtkTextView widget. While the GAIL ATK implementation for GTK+ widgets can be used as a sample ATK implementation, it may not represent the ideal implementation. For recommended ATK implementations (interfaces, states, role, actions, relations, events, etc) for common UI widgets, refer to the UI 11.3 Recommended ATK Implementations for Common UI Components].

Widget

GAIL
Implementation

GAIL
Inheritance

ATK
Interfaces

ATK_ROLE

GtkWidget

GailWidget

AtkComponent,
AtkObject,
AtkStateSet,
AtkRelationSet,
AtkRelation

(base class)
ATK_ROLE_UNKNOWN

GtkLabel

GailLabel

GailWidget

AtkObject,
AtkText (AtkAttributeSet),
AtkStateSet,
AtkRelationSet

ATK_ROLE_LABEL

GtkAccelLabel

GailLabel

ATK_ROLE_ACCEL_LABEL

GtkArrow

GailArrow

GailWidget

AtkObject,
AtkImage

ATK_ROLE_ICON

GtkImage

GailImage

GailWidget

AtkObject,
AtkComponent,
AtkImage

ATK_ROLE_ICON

GtkContainer

GailContainer

GailWidget

AtkObject

ATK_ROLE_UNKNOWN or
ATK_ROLE_PANEL

GtkViewPort

GailContainer

ATK_ROLE_VIEWPORT

GtkToolbar

GailContainer

ATK_ROLE_TOOLBAR

GtkScrolledWindow

GailScrolledWindow

GailContainer

AtkObject

ATK_ROLE_SCROLL_PANE

GtkFrame

GailFrame

GailWidget

AtkObject

ATK_ROLE_PANEL

GtkButton

GailButton

GailWidget

AtkObject,
AtkComponent,
AtkAction,
AtkImage
(if an image),
AtkText (AtkAttributeSet),
AtkStateSet

ATK_ROLE_PUSH_BUTTON or
ATK_TABLE_COLUMN_HEADER (if tree view)

GtkToggleButton

GailToggleButton

GailButton

AtkObject,
AtkAction,
AtkStateSet

ATK_ROLE_TOGGLE_BUTTON

GtkCheckButton

GailToggleButton

ATK_ROLE_CHECK_BOX

GtkRadioButton

GailRadioButton

GailToggleButton

AtkObject,
AtkRelationSet,
AtkRelation

ATK_ROLE_RADIO_BUTTON

GtkExpander

GailExpander

GailContainer

AtkObject,
AtkText (AtkAttributeSet),
AtkAction,
AtkStateSet

ATK_ROLE_TOGGLE_BUTTON

GtkItem

GailItem

GailContainer

AtkObject,
AtkText (AtkAttributeSet)

ATK_ROLE_LIST_ITEM

GtkMenuItem

GailMenuItem

GailWidget

AtkObject,
AtkAction

ATK_ROLE_MENU_ITEM

GtkSeparatorMenuItem

GailMenuItem

ATK_ROLE_SEPARATOR

GtkTearOffMenuItem

GailMenuItem

ATK_ROLE_TEAR_OFF_MENU_ITEM

GtkCheckMenuItem

GailCheckMenuItem

GailMenuItem

AtkObject,
AtkStateSet

ATK_ROLE_CHECK_MENU_ITEM

GtkRadioMenuItem

GailRadioMenuItem

GailCheckMenuItem

AtkObject,
AtkRelationSet

ATK_ROLE_RADIO_MENU_ITEM

GtkMenuShell

GailMenuShell

GailContainer,
GailWidget

AtkObject,
AtkSelection

ATK_ROLE_MENU_BAR

GtkMenu

GailMenu

GailMenuShell

AtkObject

ATK_ROLE_MENU

GtkMenuBar

GailMenuShell

ATK_ROLE_MENU_BAR

GtkWindow

GailWindow

GailWidget

AtkObject,
AtkComponent,
AtkRelation,
AtkRelationSet,
AtkStateSet

ATK_ROLE_WINDOW or
ATK_ROLE_PANEL or
ATK_ROLE_FRAME

GtkDialog

GailWindow

ATK_ROLE_DIALOG

GtkColorSelectionDialog

GailWindow

ATK_ROLE_COLOR_CHOOSER

GtkFileSelection

GailWindow

ATK_ROLE_FONT_CHOOSER

GtkColorSelection

GailWindow

ATK_ROLE_COLOR_CHOOSER

GtkFontSelection

GailWindow

ATK_ROLE_FONT_CHOOSER

GtkFontSelectionDialog

GailWindow

ATK_ROLE_DIALOG

GtkMessageDialog

GailWindow

ATK_ROLE_ALERT

GtkHandleBox

GailWindow

ATK_ROLE_WINDOW

GtkTooltips

GailWindow

ATK_ROLE_TOOL_TIP

GtkBox

GailBox

GailContainer

AtkObject,
AtkStateSet

ATK_ROLE_FILLER

GtkButtonBox

GailBox

ATK_ROLE_FILLER

GtkHButtonBox

GailBox

ATK_ROLE_FILLER

GtkVButtonBox

GailBox

ATK_ROLE_FILLER

GtkHBox

GailBox

ATK_ROLE_FILLER

GtkComboBox

GailComboBox

GailContainer

AtkObject,
AtkAction,
AtkSelection

ATK_ROLE_COMBO_BOX

GtkStatusBar

GailStatusBar

GailContainer

AtkObject,
AtkText (AtkAttributeSet)

ATK_ROLE_STATUSBAR

GtkFixed

GailContainer

ATK_ROLE_UNKNOWN

GtkPaned

GailContainer

ATK_ROLE_UNKNOWN

GtkHPaned

GailContainer

ATK_ROLE_UNKNOWN

GtkVpaned

GailContainer

ATK_ROLE_UNKNOWN

GtkLayout

GailContainer

ATK_ROLE_UNKNOWN

GtkPacker

GailContainer

ATK_ROLE_UNKNOWN

GtkTable

GailContainer

ATK_ROLE_UNKNOWN

GtkNotebook

GailNotebook

GailWidget

AtkObject,
AtkSelection

ATK_ROLE_PAGE_TAB_LIST

GtkTreeView

GailTreeView

GailContainer

AtkObject,
AtkComponent,
AtkTable,
AtkSelection,
AtkRegistry,
AtkObjectFactory,
AtkRelationSet,
AtkRelation,
AtkStateSet

ATK_ROLE_TREE_TABLE or
ATK_ROLE_TABLE or
ATK_ROLE_UNKNOWN

GtkCellRenderer

GailRendererCell

GailWidget

AtkObject

ATK_ROLE_TABLE_CELL

GtkCellRendererText

GailTextCell

GailWidget

AtkObject,
AtkText (AtkAttributeSet)

ATK_ROLE_TABLE_CELL

GtkCellRendererToggle

GailBooleanCell

GailWidget

AtkObject

ATK_ROLE_TABLE_CELL

GtkCellRendererPixbuf

GailImageCell

GailWidget

AtkObject,
AtkImage,
AtkComponent

ATK_ROLE_TABLE_CELL

GtkTextView

GailTextView

GailContainer

AtkObject,
AtkEditableText,
AtkText (AtkAttributeSet),
AtkStateSet
(Why not AtkHyperlink
and AtkHypertext for when there
are links and AtkTable for when
there's a table?)

ATK_ROLE_TEXT

GtkCalendar

GailCalendar

GailWidget

AtkObject
(Why not AtkSelection?)

ATK_ROLE_CALENDAR

GtkEntry

GailEntry

GailWidget

AtkObject,
AtkEditableText,
AtkText (AtkAttributeSet),
AtkRelation,
AtkRelationSet,
AtkStateSet,
AtkAction

ATK_ROLE_TEXT or
ATK_PASSWORD_TEXT

GtkSpinButton

GailSpinButton

GailWidget

AtkObject,
AtkValue

ATK_ROLE_SPIN_BUTTON

GtkRange

GailRange

GailWidget

AtkObject,
AtkValue,
AtkStateSet

ATK_ROLE_SLIDER

GtkScale

GailScale

GailRange

AtkObject,
AtkText (AtkAttributeSet)

(base class)

GtkHScale

GailScale

GtkVScale

GailScale

GtkScrollbar

GailScrollbar

GailRange

AtkObject

ATK_ROLE_SCROLLBAR
(base class)