PLEASE NOTE: This document is no longer being maintained and eventually will be deleted. Instead, please refer to the GNOME Desktop Accessibility Guide which includes the information found on this page.

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;
    
              [[http://library.gnome.org/devel/gtk/unstable/GtkLabel.html|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)
    Note there is also a simpler API (atk_object_add_relationship) which can be used to add relationship between two widgets.
    • C example:

      {
    
              GtkWidget *widget;
    
              [[http://library.gnome.org/devel/gtk/unstable/GtkLabel.html|GtkLabel]] *label;
    
              AtkObject *atk_widget, *atk_label;
    
              atk_widget = gtk_widget_get_accessible (widget);
    
              atk_label = gtk_widget_get_accessible (GTK_WIDGET (label));
    
              atk_object_add_relation (atk_label, ATK_RELATION_LABEL_FOR, atk_widget);
    
              atk_object_add_relation (atk_widget, ATK_RELATION_LABELLED_BY, atk_label);
    
      }
  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 AtkRelation 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 GtkTable, 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)

GtkHScrollbar

GailScrollBar

GtkVScrollbar

GailScrollBar

GtkSeparator

GailSeparator

GailWidget

AtkObject,
AtkStateSet

ATK_ROLE_SEPARATOR
(base class)

GtkHSeparator

GailSeparator

GtkVSeparator

GailSeparator

GtkProgressbar

GailProgressBar

GailWidget

AtkObject,
AtkValue

ATK_ROLE_PROGRESS_BAR

GtkAdjustment

GailAdjustment

GailWidget

AtkObject,
AtkValue

ATK_ROLE_UNKNOWN

Accessibility/Documentation/GNOME2/AtkGuide/GtkAtk (last edited 2011-07-21 17:35:16 by JoanmarieDiggs)