Aaron Leventhal, IBM
Cathy Laws, IBM
Larry Weiss, IBM
Pete Brunet, IBM
Bill Haneman, Sun Microsystems
OVERVIEW
This document specifies different ways that document content can be efficiently exposed using the existing ATK/AT-SPI with minimum modifications to the ATK/AT-SPI specifications. It does so by effectively creating a containment hierarchy based upon a relevant subset of the DOM, where each container has an accessible role which is mapped to AtkRoleTypes from the associated element type (e.g., "html:h1", "html:h2", "html:a", html:p", etc.). Contiguous regions of text typically appear as children that are accessible text objects, and other components (e.g., widgets inside forms) appear as their associated ATK/AT-SPI counterparts. Furthermore, CSS attributes will be represented as AT-SPI text attributes.PROBLEM STATEMENT
Screen reader users need the ability to:- Navigate documents by higher level structure
- Know where they are within the current document's structure
Furthermore, requirement 2 really means that the screen reader needs to be able to determine document structure anyway.
The current ATK implementation in Gecko has the following problems, when exposing document structure:
- It does not expose headings, quotations, paragraphs, forms, list containers and other structural objects
- It is not possible to differentiate sequential or nested lists from each other or even from a single large list. The list items are simply exposed one after the next.
- There is confusion about embedded objects. They are currently exposed out of order relative to where they actually exist in the document. Gecko must do extra error-prone work to expose them in the new order, and the AT must unravel that. In addition, the extra work in the Gecko implementation makes code reuse with the Windows/MSAA implementation difficult.
- There is confusion about links. In HTML links can span entire paragraphs or a complex set of objects. This is not modeled well with the current system.
PROPOSAL
The proposal is relatively simple:
- Continue to map HTML constructs to existing AT-SPI roles.
- Expose
structural HTML element roles as AtkObject attributes. The
corresponding attribute name will be "html:role", and the value of that
attribute will be the actual HTML tag.
- Treat container elements as containers which can have children. Embedded objects, links and other containers will appear as children of these containers. Furthermore, objects embedded within text content will be exposed via an AtkHypertext implementation on the containing text object. (In some cases the text object will have empty text content, and AT clients should be prepared to handle those cases).
- Expose text with one of 3 methods:
- [currently not recommended] expose text as child text leaf nodes with a role of "text", or
- [currently not recommended] Expose contatenated text on the container for the text, using unicode 0xfffc to indicate embedded objects. A general rule is: if something exposing AccessibleText has children, then each child will be marked in the text with 0xfffc
- [preferred as of 3-29-06] Implement AtkHypertext on text containing embedded content as well as text containing HTML anchors. Treat all children as AtkHyperlinks, even if they're not technically links.
- Treate image maps as a container image which implements AtkHyperlink objects with multiple anchors.
- Implement the AtkHyperlinks returned by AtkHypertext as
full-fledged AtkObjects, and expose them as children of the
AtkHypertext parent.
- The following interfaces would be supported: AccessibleAction, AccessibleComponent, AccessibleHyperText, AccessibleText, AccessibleEditableText, AccessibleImage, AccessibleSelection, AccessibleTable, AccessibleValue, AccessibleRelation
- AccessibleTable would be implemented on the <table> object, and the children could also be obtained by walking the regular hierarchy.
NEW API
ATK_ROLE_FORM may be needed as an enhancement. We may also need
ATK_RELATION_DESCRIPTION_FOR/DESCRIBED_BY in order to better map to
MSAA.All items that can be interacted with via the keyboard will support
the FOCUSABLE, FOCUSED, ENABLED and SENSITIVE states, and will
emit "focus:" events when
they receive focus. All items that display text will
implement Accessibility_Text. Furthermore, "object:text-caret-moved"
events should be emitted by the associated text object as the caret
moves. Items within combos and selectable lists will have
SELECTABLE, and lists supporting multiple selections will have
MULTISELECT. Read-only objects of types or exposing interfaces
which are ordinarily editable will have the READONLY state.
REQUIRED will be exposed as appropriate.
NOTE: The sttribute pattern of "html:role=tag" can also be carried over to other XML specifications, such as SVG, MATHML, ODF, etc. The general pattern is "namespaceabbrev:role=tag".
ADVANTAGES
- Document structure exposed. Screen reader can get info it needs.
- Simplfies implementation both for Gecko and for screen readers
- Backwards-compatible with GOK
- Synchronizes ATK implementation with MSAA implementation, making an implementation for advanced text interfaces on Windows much easier down the road, by allowing reuse of all the classes which implement special interfaces (text, tables, etc.). With this huge difference removed, most of the important code to implement those interfaces can be moved into the cross-platform implenentation.
Q & A
Q. How is the checkable state of a menuitem, treeitem or listitem
exposed?
A. See ATK_STATE_CHECKED, AtkAction, and ATK_ROLE_CHECK_BOX, etc.
Q. How do I support the valuechange event? It is
too difficult to find the old value.
A. The spec doesn't actually say what detail1 & detail2 are for the
valuechange event. The AT does not need them. It gets everything it
needs from AccessibleValue, so disregard those detail1 and detail2 for
valuechange events. However, the atk-bridge should be updated,
and the spec enhanced, to add the new and old values to the "any"
struct currently dispatched with change events, and provide
Accessibility::ValueChangeEvent_getValues(), similar to what it now
does with TextChangeEvent_getChangeString().
Q; How do I expose the indeterminate state of a progressbar?
A. Expose ATK_STATE_INDETERMINATE on the progressbar.
Q. How can an AT like a magnifier scroll to a particular piece of
text?
A. Set the caret before the word you want to scroll to [this is a
policy proposal that is not yet defined.]
Q. How should an application indicate that an alert, which will not
receive focus, has become visible?
A. Use the children-changed event, and use ATK_ROLE_ALERT on the newly
created alert object. If the alert has its own window, then the
"window:create" event should be emitted to indicate when
an alert becomes visible or a state-change event for the visible
state.
Q: What's visible-data-changed?
A: It's a sort of catch-all that says "the onscreen content of this
object has changed in a way that is not efficiently conveyed via
bounds-changed, text-changed, selection-changed, or similar more
specific events"... mostly it says to the AT, "refresh all your cached
info about this object's onscreen representation". [Note that there is also a
model-change-event I think, which may sometimes be more
appropriate? Need to check this]
Q. How do we expose the visited state for a link?
A. For now you need to use ATK_STATE_CHECKED, but in the future we hope
to add ATK_STATE_VISITED to the API (mapping to MSAA TRAVERSED)
Q. Should an assistive technology use role indentifiers or role
strings?
A. ATs should use the enumerated role identifiers in virtually
all cases.
ISSUES TO BE RESOLVED
- This proposal currently does not yet provide a way to expose tag names for all elements, DOM attribute/value pairs, computed style attribute/value pairs associated with individual elements, such as the size of a table cell's border. Do we need to add a getProperty(name) method to the Accessibility_Accessible interface? Do we need an Accessibility_DOMNode interface?
- ANSWER: We already have
Accessibility_Accessible::getAttributes, so this problem is solved in
theory.
- Need to document how text selection is exposed
- ANSWER: See the AtkText interface docs, in particular the text-selection-changed events, and atk_text_get_selection and atk_text_get_nselections.
- This proposal does not deal with multiple roles from DHTML. Presumably the html:role attribute value could consist of a list of role names with some delimiters between them.
- Should a separate role or text attribute be maintained for text which is inserted by the rendering environment, such as list bullet text, :before/:after styled text? In MSAA the separate "static text" role is used.
- ANSWER: This should be exposed as a text attribute, potentially
called "static".
- Should we remove the "html:" prefix from common roles that we'll want to reuse for ODF, such as "h1"?
- ANSWER: Probably not, but we may wish to expose common
attributes such as "heading level=1" in addition to the html tag name
literal.
- Is it currently possible to get the URL, mime type or doctype for a document?
- ANSWER: Yes - either via AtkDocument:;getDocumentAttributes, or
(preferably) by implementing AtkStreamableContent on the document
container.
EXAMPLES
The following examples provide a mapping between HTML and the ATK representation. In each of the following examples, an ATK accessible object is encapsulated in braces ("{}"), and meaningful ATK interfaces and attributes, including specializations, are represented as name/value pairs inside the braces. For convenience, accessible text is shown merely as 'text="contents of the text"'.
To do: HTML table & DHTML role exampleNote: everything supports AtkObject and AtkComponent
HTML content | HTML source | ATK with text in leaves |
ATK with text in containers |
ATK using Hypertext and Hyperlink children |
---|---|---|---|---|
This is a headingThis is a paragraph with an image in it. This is another heading |
<h1>This is a heading</h1> |
{parent role="html:h1"} |
{parent AtkText, role="html:h1", |
{parent AtkText, role=ATK_ROLE_HEADING, attr="xhtml:role=h1", |
Hey! |
<p>Hey!<br>Tell me something.</p> |
{parent role="html:p"} |
{parent AtkText, role="html:p"} |
{parent AtkText, role=ATK_ROLE_PARAGRAPH, attr="xhtml:role=p"} |
Hey! Tell me something. |
<a href="http://www.google.com">Hey!
|
{parent role="html:a"}
{child AtkHypertext, AtkAction,
AtkText, role=ATK_ROLE_TEXT, text="Hey!"
{child role="html:br"}
{child AtkHypertext, AtkAction,
AtkText, role=ATK_ROLE_TEXT,
text="Tell me something."}
|
{parent AtkText, AtkAction, |
{parent AtkHyperlink, AtkText, role=ATK_ROLE_LINK |
Hey Tell me something |
<p>Hey</p><hr/>
|
{parent role="html:p"}
|
{parent AtkText, role="html:p", text="Hey"} {parent role=ATK_ROLE_SEPARATOR} {parent AtkText, role="html:p", text="Tell me something"} |
{parent1 AtkText, role=ATK_ROLE_PARAGRAPH, text="Hey"} {parent2 role=ATK_ROLE_SEPARATOR, [note: AtkState doesn't include ATK_STATE_VERTICAL, to distinguish from vsep]} {parent3 AtkText, role=ATK_ROLE_PARAGRAPH, text="Tell me something"} |
You are a nice person. |
<p> |
{parent role="html:p"} |
{parent AtkText, role="html:p", text="You are a nice person", attribute run for "are"} |
{parent AtkText,
role=ATK_ROLE_PARAGRAPH, attr="html:role=p", text="You are a nice person", attribute run for "are", with textattr="em=true, css:text-style=oblique"} [note that text attributes 'em' and 'oblique' are not entirely redundant - one is semantic, the other is presentational, so we include both. Not sure what the namespaces for semantic tags such as 'em', 'samp' and 'cite' should be.] |
Here is a bartending site. |
<p> |
{parent role="html:p"} |
{parent AtkText,
role="html:p", text="Here is a ?."} {child AtkText, AtkHypertext, role="html:a", text="bartending site", URI="http://foo.bar.com"} |
{parent AtkHypertext,
role=ATK_ROLE_PARAGRAPH, attr="html:role=p" text="Here is a bartending site.", attribute run for "bartending site." with textattr="link=true, css:text-decoration=underline, css:color=(0,0,255)"} {child AtkText, AtkHyperlink, role=ATK_ROLE_LINK, attr="html:role=a, link-type:anchor", text="bartending site", hyperlink-indices=[10,26] hyperlink-URI="http://foo.bar.com"} |
Here is a bartending site. |
<p> |
{parent role="html:p"}Problem: How to expose the image filename in ATK? Proposal: add method to AtkImage |
{parent AtkText,
role="html:p", text="Here is a ?."} {child AtkText, AtkHypertext, role="html:a", text="? bartending site", URI="http://foo.bar.com"} {grandchild AtkImage, role=ATK_ROLE_IMAGE, AccName/ImageDescription="beer glass"} |
{parent AtkHypertext,
role=ATK_ROLE_PARAGRAPH, attr="html:role=p" text="Here is a bartending site." attribute run for "bartending site." with textattr="link=true, css:text-decoration=underline, css:color=(0,0,255)"} {child AtkHypertext, AtkHyperlink, role=ATK_ROLE_LINK, text="bartending site" hypertext-indices=[10,26], [not sure if we need to dup textattrs here, or add them to defaulttextattrs], hypertext-URI="http://foo.bar.com"} {grandchild AtkImage, AtkHyperlink role=ATK_ROLE_IMAGE, attr="html:role=img, link-type=image" AccName/ImageDescription="beer glass", hyperlink-indices=[0,0] hyperlink-URI="beerglass.GIF"} [don't know if the URIs should always be fully specified, or if omitting the base URI is OK] |
Here is a bartending site . |
<p> |
{parent role="html:p"} |
{parent AtkText,
role="html:p", text="Here is a ??"} {child AtkImage, role=ATK_ROLE_IMAGE, AccName/ImageDescription="beer glass"} {child AtkText, AtkHypertext, role="html:a", text="bartending site", URI="http://foo.bar.com"} |
{parent AtkHypertext,
role=ATK_ROLE_PARAGRAPH, attr="html:role=p", text="Here is a bartending site."} {child AtkImage, AtkHyperlink, role=ATK_ROLE_IMAGE, attr="html:role=img, link-type=image" AccName/ImageDescription="beer glass", hyperlink-indices=[10,10] hyperlink-URI="beerglass.GIF"} {child AtkText, AtkHyperlink, AtkAction, AtkHypertext, role=ATK_ROLE_LINK, action-names="activate", [others?] attr="html:role=a, link-type=anchor" text="bartending site", textattr=[as in above examples] hypertext-indices=[10,26], hypertext-URI="http://foo.bar.com"} |
<p> |
{parent role="html:p"} |
{parent AtkText, role="html:p", |
{parent AtkHypertext, role=ATK_ROLE_PARAGRAPH, |
|
|
<ul> |
{parent role="html:ul"} |
{parent AtkText, role="html:ul", text="??"} |
[we should be able to support list-style=image, and "list-style-image=URL()", etc. this way. In the above example, it's not clear whether the bullet should be a unicode char or just omitted and implied by the list style.. my guess is the latter (i.e. bullets don't appear in the text)] |
|
<ol> |
{parent role="html:ol"} |
{parent AtkText, role="html:ol", text="??"} |
{parent AtkObject, role=ATK_ROLE_LIST, attr="html:role=ol, css:list-style-type:decimal"} |
|
<ul> |
{parent role="html:ul"} |
{parent AtkText, role="html:ul", |
|
<form> |
{parent role="html:form"} |
{parent AtkText, role="html:form", text="??"} |
{parent AtkObject, role=ATK_ROLE_FORM, text=""} |
|
<form aaa:describedby="checkhelp"> |
{parent role="html:form", |
{parent AtkText, |
{parent AtkObject, |
|
<form> |
{parent role="html:form"} |
{parent role="html:form"} |
{parent role=ATK_ROLE_FORM?} |
|
<form> |
{parent role="html:form"} |
{parent AtkText, |
{parent role=ATK_ROLE_FORM?} |