You are viewing information archived from Mozilla.org on 2015-08-05.

EXPOSING HTML/DOM VIA ATK/AT-SPI

Contributors

Will Walker, Sun Microsystems
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:
  1. Navigate documents by higher level structure
  2. Know where they are within the current document's structure
Although requirement 1 can be filled by an improved caret navigation capability, that would force synchronization of the screen reader and the document's point of regard, which is not always possible -- for example, the Firefox caret cannot be set within a list of options, for example. The caret browsing system is difficult to maintain because the two can be out of sync.

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:
  1. It does not expose headings, quotations, paragraphs, forms, list containers and other structural objects
  2. 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.
  3. 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. 
  4. 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:

  1. Continue to map HTML constructs to existing AT-SPI roles.
  2. 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.

  3. 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).
  4. Expose text with one of 3 methods:
    1. [currently not recommended] expose text as child text leaf nodes with a role of "text", or
    2. [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
    3. [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.
  5. Treate image maps as a container image which implements AtkHyperlink objects with multiple anchors.
  6. Implement the AtkHyperlinks returned by AtkHypertext as full-fledged AtkObjects, and expose them as children of the AtkHypertext parent.

  7. The following interfaces would be supported: AccessibleAction, AccessibleComponent, AccessibleHyperText, AccessibleText, AccessibleEditableText, AccessibleImage, AccessibleSelection, AccessibleTable, AccessibleValue, AccessibleRelation
  8. 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

  1. Document structure exposed. Screen reader can get info it needs.
  2. Simplfies implementation both for Gecko and for screen readers
  3. Backwards-compatible with GOK
  4. 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

  1. 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?
    1. ANSWER: We already have Accessibility_Accessible::getAttributes, so this problem is solved in theory.

  2. Need to document how text selection is exposed
    1. ANSWER: See the AtkText interface docs, in particular the text-selection-changed events, and atk_text_get_selection and atk_text_get_nselections.
  3. 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.
  4. 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.
    1. ANSWER: This should be exposed as a text attribute, potentially called "static".

  5. Should we remove the "html:" prefix from common roles that we'll want to reuse for ODF, such as "h1"?
    1. ANSWER: Probably not, but we may wish to expose common attributes such as "heading level=1" in addition to the html tag name literal.

  6. Is it currently possible to get the URL, mime type or doctype for a document?
    1. 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 example

Note: 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 heading

This is a paragraph with an some image image in it.

This is another heading

<h1>This is a heading</h1>
<p>
This is a paragraph with an
<image src="image.gif"
alt="some image"/>
image in it.
</p>
<h2>This is another heading</h2>








{parent role="html:h1"}
{child AtkText, role=ATK_ROLE_TEXT,
text="This is a heading"}
{parent role="html:p"}
{child AtkText, role=ATK_ROLE_TEXT,
text="This is a paragraph with an"}
{child AtkImage, role=ATK_ROLE_IMAGE,
AccName/ImageDescription ="some image"}
{child AtkText, role=ATK_ROLE_TEXT,
text="image in it."}
{parent role="html:h2"}
{child AtkText, role=ATK_ROLE_TEXT,
text="This is another heading"}











{parent AtkText, role="html:h1",
text="This is a heading"}
{parent AtkText, role="html:p",
text="This is a paragraph with an ? image in it"}
{child AtkImage, role=ATK_ROLE_IMAGE,
AccName/ImageDescription ="some image"}
{parent AtkText, role="html:h2",
text="This is another heading"}







{parent AtkText, role=ATK_ROLE_HEADING, attr="xhtml:role=h1",
text-attributes="css:font-size=LARGER",
text="This is a heading"}
{parent AtkHypertext, role=ATK_ROLE_PARAGRAPH, attr="xhtml:role=p"
text="This is a paragraph with an image in it"}
{child AtkImage, AtkHyperlink, role=ATK_ROLE_IMAGE,
ImageDescription ="some image",
AccessibleName = "" [the HTML title attribute, if present]
hyperlink-range=[28,28]}
{parent AtkText, role=ATK_ROLE_HEADING, attr="xhtml-role:h2",
text-attributes="css:font-size=LARGE",
text="This is another heading"}










Hey!
Tell me something.

<p>Hey!<br>Tell me something.</p>
{parent role="html:p"}
{child AtkText, role=ATK_ROLE_TEXT,
text="Hey!"}
{child role="html:br"}
{child AtkText, role=ATK_ROLE_TEXT,
text="Tell me something."}





{parent AtkText, role="html:p"}
text="Hey!?Tell me something"}
{child role="html:br"}


{parent AtkText, role=ATK_ROLE_PARAGRAPH, attr="xhtml:role=p"}
text="Hey!\nTell me something"}


Hey!
Tell me something.
<a href="http://www.google.com">Hey!
<br>Tell me something.</a>

{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,
role="html:a", AtkHypertext,
text="Hey!?Tell me something"}
{child role="html:br"}



{parent AtkHyperlink, AtkText, role=ATK_ROLE_LINK
attr="xhtml:role=a;link-type=anchor",
text="Hey!\nTell me something",
hyperlink-range=[depends on the containing context],
hyperlink-URI="http://www.google.com",
hyperlink-Object=AtkText}




Hey


Tell me something

<p>Hey</p><hr/>
<p>Tell me something</p>
{parent role="html:p"}
{child AtkText, role=ATK_ROLE_TEXT,
text="Hey"}
{parent role=ATK_ROLE_SEPARATOR}
{parent role="html:p"}
{child AtkText, role=ATK_ROLE_TEXT,
text="Tell me something"}





{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>
You <em>are</em> a nice person.
</p>

{parent role="html:p"}
{child AtkText,
role=ATK_ROLE_TEXT, text="You "}
{child AtkText,
role=ATK_ROLE_TEXT, text="are",
attr_style="italic"}
{child AtkText, role=ATK_ROLE_TEXT,
text=" a nice person."}






{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>
  Here is a
  <a href="http://foo.bar.com">
   bartending site
  </a>
.
</p>





{parent role="html:p"}
{child AtkText, role=ATK_ROLE_TEXT,
text="Here is a "}
{child role="html:a",
{grandchild AtkHypertext, AtkText,
role=ATK_ROLE_TEXT, text="bartending site",
URI="http://foo.bar.com"}

{child AtkText,
role=ATK_ROLE_TEXT, text="."}








{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 beer glassbartending site.

<p>
Here is a
<a href="http://foo.bar.com">
<image src="beerglass.GIF"
alt="beer glass"/>
bartending site
</a>
.
</p>







{parent role="html:p"}
{child AtkText, role=ATK_ROLE_TEXT,
text="Here is a "}
{child role="html:a"}
{grandchild AtkHypertext,
AtkImage, role=ATK_ROLE_IMAGE,
AccName/ImageDescription="beer glass",
URI="http://foo.bar.com"}
{grandchild AtkHypertext,
AtkText, role=ATK_ROLE_TEXT,
text/name="bartending site",
URI="http://foo.bar.com" }
{child AtkText,
role=ATK_ROLE_TEXT, text="."}












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 beer glass bartending site .

<p>
Here is a
<image src="beerglass.GIF"
alt="beer glass"/>
<a href="http://foo.bar.com">
bartending site
</a>
.
</p>







{parent role="html:p"}
{child AtkText, role=ATK_ROLE_TEXT,
text="Here is a "}
{child AtkImage,
role=ATK_ROLE_IMAGE,
AccName/ImageDescription="beer glass"}
{child role="html:a"}
{grandchild AtkHypertext,
AtkAction, AtkText,
role=ATK_ROLE_TEXT,
text/name="bartending site",
URI="http://foo.bar.com" }
{child AtkText,
role=ATK_ROLE_TEXT, text="."}












{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>
<IMG SRC="sitemap.gif"
ALT="Site map"
USEMAP="#mymap"></p>
<MAP NAME="mymap" title="site map">
<AREA HREF="1.html" ALT="Bar"
COORDS="5,5,95,195">
<AREA HREF="2.html" ALT="Baz"
COORDS="105,5,195,195">
<AREA HREF="3.html" ALT="Fu"
COORDS="205,5,295,195">
</MAP>
</p>











{parent role="html:p"}
{child AtkImage,
role="html:map",
AccName and ImageDescription="Site map",
AccDescription="site map"}
{grandchild AtkHypertext, AtkAction,
role="html:area", URI="1.html", name="Bar"}
{grandchild AtkHypertext, AtkAction,
role="html:area", URI="2.html", name="Baz"}
{grandchild AtkHypertext, AtkAction,
role="html:area", URI="3.html", name="Fu"}









{parent AtkText, role="html:p",
AtkText="?"}
{child AtkImage,
role="html:map",
AccName and ImageDescription="Site map"}
{grandchild AtkHypertext, AtkAction,
role="html:area", URI="1.html", name="Bar"}
{grandchild AtkHypertext, AtkAction,
role="html:area", URI="2.html", name="Baz"}
{grandchild AtkHypertext, AtkAction,
role="html:area", URI="3.html", name="Fu"}









{parent AtkHypertext, role=ATK_ROLE_PARAGRAPH,
text=""}
{child AtkImage, AtkHypertext,
role=ATK_ROLE_IMAGE_MAP,
attr="html:role=map",
hyperlink-URI="sitemap.gif",
ImageBounds=[entire map area]
AccName and ImageDescription="Site map"}
{grandchild AtkHyperlink, AtkAction,
action-names="click", role=ATK_ROLE_LINK,
attr="html:role=area", hyperlink-URI="1.html", name="Bar"}
{grandchild AtkHyperlink, AtkAction,
action-names="click", role=ATK_ROLE_LINK,
attr="html:role=area", hyperlink-URI="2.html", name="Baz"}
{grandchild AtkHyperlink, AtkAction,
action-names="click", role=ATK_ROLE_LINK,
attr="html:role=area", hyperlink-URI="3.html", name="Fu"}
[note that the component bounds of the areas correspond to their rectangular bounding boxes]
















  • This is a list item.
  • This is another list item.
<ul>
<li>This is a list item.</li>
<li>This is another list item.</li>
</ul>


{parent role="html:ul"}
{child role="html:li"}
{grandchild AtkText,
role=ATK_ROLE_TEXT, text=<<<bullet>>>}
{grandchild AtkText,
role=ATK_ROLE_TEXT,
text="This is a list item."}
{child role="html:li"}
{grandchild AtkText,
role=ATK_ROLE_TEXT, text=<<<bullet>>>}
{grandchild AtkText,
role=ATK_ROLE_TEXT,
text="This is another list item."}











{parent AtkText, role="html:ul", text="??"}
{child AtkText, role="html:li",
text="<<<bullet>>> This is a list item."}
{child AtkText, role="html:li",
text="<<<bullet>>> This is another list item."}





{parent AtkObject, role=ATK_ROLE_LIST, attr="css:list-style-type=disc"}
{child AtkText, role=ATK_ROLE_LIST_ITEM,
text="This is a list item.", attribute run "static" first 2 chars}
{child AtkText, role=ATK_ROLE_LIST_ITEM,
text="This is another list item.", attribute run "static" first 2 chars}






[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)]
  1. This is a list item.
  2. This is another list item.
<ol>
<li>This is a list item.</li>
<li>This is another list item.</li>
</ol>


{parent role="html:ol"}
{child role="html:li"}
{grandchild AtkText,
role=ATK_ROLE_TEXT, text="1."}
{grandchild AtkText,
role=ATK_ROLE_TEXT,
text="This is a list item."}
{child role="html:li"}
{grandchild AtkText,
role=ATK_ROLE_TEXT, text="2."}
{grandchild AtkText,
role=ATK_ROLE_TEXT,
text="This is another list item."}











{parent AtkText, role="html:ol", text="??"}
{child AtkText, role="html:li",
text="1. This is a list item."}
{child AtkText, role="html:li",
text="2. This is another list item."}





{parent AtkObject, role=ATK_ROLE_LIST, attr="html:role=ol, css:list-style-type:decimal"}
{child AtkText, role=ATK_ROLE_LIST_ITEM,
text="1. This is a list item.", attribute run "static" first 3 chars}
{child AtkText, role=ATK_ROLE_LIST_ITEM,
text="2. This is another list item.", attribute run "static" first 3 chars}

[we should clearly define a text attribute which means "this text is
not explicit in the content, but was added by the presentation/user agent. I
believe MSAA/IE uses "static" ?]










  • This is a list item
    • Nested item 1.
    • Nested item 2.

  • This is another list item.
<ul>
<li>
This is a list item.
<ul>
<li>Nested item 1</li>
<li>Nested item 2</li>
</ul>
</li>
<li>This is another list item.</li>
</ul>








{parent role="html:ul"}
{child role="html:li"}
{grandchild AtkText,
role=ATK_ROLE_TEXT, text=<<<bullet>>>}
{grandchild AtkText,
role=ATK_ROLE_TEXT,
text="This is a list item."}
{grandchild role="html:ul"}
{great-grandchild role="html:li"}
{great-great-grandchild AtkText,
role=ATK_ROLE_TEXT, text=<<<bullet>>>}
{great-great-grandchild AtkText,
role=ATK_ROLE_TEXT, text="Nested item 1"}
{great-grandchild role="html:li"}
{great-great-grandchild AtkText,
role=ATK_ROLE_TEXT, text=<<<bullet>>>}
{great-great-grandchild AtkText,
role=ATK_ROLE_TEXT,
text="Nested item 2"}
{child role="html:li"}
{grandchild AtkText,
role=ATK_ROLE_TEXT, text=<<<bullet>>>}
{grandchild AtkText,
role=ATK_ROLE_TEXT,
text="This is another list item."}























{parent AtkText, role="html:ul",
text="??"}
{child AtkText, role="html:li",
text="<<<bullet>>> This is a list item.?"}
{grandchild AtkText, role="html:ul",
text="??"}
{great-grand-child AtkText,
role="html:li",
text="<<<bullet>>> Nested item 1"}
{great-grand-child AtkText,
role="html:li",
text="<<<bullet>>> Nested item 2"}

{child AtkText, role="html:li",
text="<<<bullet>>> This is another list item."}
















{parent AtkObject, role=ATK_ROLE_LIST, attr="html:role=ul, css:list-style-type=disc"}
{child AtkHypertext, role=ATK_ROLE_LIST_ITEM,
text="This is a list item."}
{grandchild AtkObject, AtkHyperlink, role=ATK_ROLE_LIST,
attr="html:role=ul, css:list-style-type=circle, link-type=child",
hyperlink-indices=[20,20],
hyperlink-URI="", [Hmm, degenerate case here...] }
{great-grandchild AtkText, role=ATK_ROLE_LIST_ITEM, attr="html:role=li"
text="Nested item 1"}
{great-grandchild AtkText, role=ATK_ROLE_LIST_ITEM, attr="html:role=li"
text="Nested item 2"}
   {child AtkText, role=ATK_ROLE_LIST_ITEM,
text="This is another list item."}


[Note that unlike user interface ATK_ROLE_LIST objects, these lists don't
implement AtkSelection, and the list items' AtkStateSets do not include
ATK_STATE_SELECTABLE. There is a question here as to whether <ul> and <ol> elements
should always implement AtkText or not. I think it would be better if they did not, unless they had
non-empty text content, but this may prove impractical.]


















<form>
<div>
 <label for="self"/>
Tell me a little more:
</label>
</div>
<div>
<textarea>
I am a monkey with a long
tail. I like to swing from
trees and eat bananas. I've
recently taken up typing
and plan to write my memoirs.
</textarea>
</div>
</form>














{parent role="html:form"}
{child role="html:div"}
{grandchild AtkRelation,
role=ATK_ROLE_LABEL,
ATK_RELATION_LABEL_FOR}
{great-grandchild AtkText, role=ATK_ROLE_TEXT,
text/name="Tell me a little more:"}
{child role="html:div"}
{grandchild AtkEditableText,
AtkRelation, AtkStateSet, AtkAction,
or ATK_ROLE_ENTRY,
text="I am a monkey with ..."},
ATK_RELATION_LABELLED_BY,
STATE_MULTILINE,

STATE_REQUIRED allowed}














{parent AtkText, role="html:form", text="??"}
{child AtkText, role="html:div",
text="?"}
{grandchild AtkText,
role=ATK_ROLE_LABEL,
ATK_RELATION_LABEL_FOR,
text="Tell me a little more:"}
{child role="html:div"}
{grandchild AtkEditableText,
AtkRelation, AtkStateSet, AtkAction,
ATK_ROLE_ENTRY,
text="I am a monkey with ..."},
ATK_RELATION_LABELLED_BY,
STATE_MULTILINE,
STATE_REQUIRED allowed}













{parent AtkObject, role=ATK_ROLE_FORM, text=""}
{child1 AtkObject, role=ATK_ROLE_SECTION? [or should we use ATK_ROLE_PANE?]}
{grandchild AtkText,
role=ATK_ROLE_LABEL,
ATK_RELATION_LABEL_FOR=child2,
text="Tell me a little more:"}
{child2 role=ATK_ROLE_SECTION?}
{grandchild AtkEditableText,
AtkRelation, AtkStateSet, AtkAction,
ATK_ROLE_ENTRY,
text="I am a monkey with ..."},
ATK_RELATION_LABELLED_BY=child1,
STATE_MULTILINE,
STATE_REQUIRED allowed}

[ attribute run over the portion of the text scrolled into view?
CONTROLLER_FOR/CONTROLLED_BY for the scrollbar/viewport?
Alternative would be to treat all the text content as though it were visible, but that's no good
for magnifiers and ATs for the mobility-impaired. Probably the textarea needs to be expanded somewhat,
or at least fitted with AtkActions for scrolling plus text attribution for determining what parts of the text are
currently scrolled into view, without the AT client having to resort to bounds checking in the
"screen review" fashion. This is, however, a general problem with multiline text in viewports.
The relatively new AtkText getBoundedRanges API reduces the pain somewhat since you can
feed it the AtkComponent bounds and it will give you back the visible text.]






















Check one or more:

<form aaa:describedby="checkhelp"> 
<p>
<span
x2:role="wairole:description"
id="checkhelp">
Check one or more:
</span>
<input id="cb1" type="checkbox"/>
<label for="cb1">Red</label>
<input id="cb2" type="checkbox"/>
<label for="cb2">Blue</label>
<input id="cb3" type="checkbox"/>
<label for="cb3">Green</label>
</p>
</form>













{parent role="html:form",
accDescription="Check one or more:"}
{child role="html:p"}
{grandchild role="wairole:description"}
{great-grandchild AtkText,
role=ATK_ROLE_TEXT,
text="Check one or more:"}
{grandchild AtkRelation, AtkAction,
AtkStateSet, role=ATK_ROLE_CHECK_BOX,
name="Red", ATK_RELATION_LABELLED_BY}
{grandchild AtkRelation, AtkText,
role=ATK_ROLE_LABEL, text="Red",
ATK_RELATION_LABEL_FOR}
{grandchild AtkRelation, AtkAction,
AtkStateSet, role=ATK_ROLE_CHECK_BOX,
name="Blue", ATK_RELATION_LABELLED_BY}
{grandchild AtkRelation, AtkText,
role=ATK_ROLE_LABEL, text="Blue",
ATK_RELATION_LABEL_FOR}
{grandchild AtkRelation, AtkAction,
AtkStateSet, role=ATK_ROLE_CHECK_BOX,
name="Green", ATK_RELATION_LABELLED_BY}
{grandchild AtkRelation, AtkText,
role=ATK_ROLE_LABEL, text="Green",
ATK_RELATION_LABEL_FOR}
Problem: need ATK_RELATION_DESCRIBED_BY
and ATK_RELATION_DESCRIPTION_FOR to match MSAA/DHTML


























{parent AtkText,
role="html:form",
accDescription="Check one or more:",
text="?"}
{child AtkText,
role="html:p", text="???????"}
{grandchild AtkText,
role="wairole:description"}
{great-grandchild AtkText,
role=ATK_ROLE_TEXT,
text="Check one or more:"}
{grandchild AtkRelation, AtkAction,
AtkStateSet, role=ATK_ROLE_CHECK_BOX,
name="Red", ATK_RELATION_LABELLED_BY}
{grandchild AtkRelation, AtkText,
role=ATK_ROLE_LABEL, text="Red",
ATK_RELATION_LABEL_FOR}
{grandchild AtkRelation, AtkAction,
AtkStateSet, role=ATK_ROLE_CHECK_BOX,
name="Blue", ATK_RELATION_LABELLED_BY}
{grandchild AtkRelation, AtkText,
role=ATK_ROLE_LABEL, text="Blue",
ATK_RELATION_LABEL_FOR}
{grandchild AtkRelation, AtkAction,
AtkStateSet, role=ATK_ROLE_CHECK_BOX,
name="Green", ATK_RELATION_LABELLED_BY}
{grandchild AtkRelation, AtkText,
role=ATK_ROLE_LABEL, text="Green",
ATK_RELATION_LABEL_FOR}
Problem: need ATK_RELATION_DESCRIBED_BY
and ATK_RELATION_DESCRIPTION_FOR to match MSAA/DHTML






























{parent AtkObject,
role=ATK_ROLE_FORM,
attr="html:role=form",
RELATION_DESCRIBED_BY=grandchild1,
text="?"}
{child AtkText,
role=ATK_ROLE_PARAGRAPH, attr="html:role=p", text=""}
{grandchild1 AtkText,
role=ATK_ROLE_LABEL,
RELATION_DESCRIPTION_FOR=parent,
attr="html:role=wairole:description"}
text="Check one or more:"}
{grandchild2 AtkAction,
AtkStateSet, role=ATK_ROLE_CHECK_BOX,
attr="html:role=input", [and same with other elements, expose html:role]
[note also that these objects do NOT have accessible names, because they are labelled;
accessible-name would presumably come from the HTML title attribute or other attribute.
This is mainly to make it easier for ATs to avoid highly redundant speech in these cases.]



ATK_RELATION_LABELLED_BY=grandchild3}
{grandchild3 AtkText,
role=ATK_ROLE_LABEL, text="Red",
ATK_RELATION_LABEL_FOR=grandchild2}
{grandchild4 AtkAction,
AtkStateSet, role=ATK_ROLE_CHECK_BOX,
ATK_RELATION_LABELLED_BY=grandchild5}
{grandchild5 AtkText,
role=ATK_ROLE_LABEL, text="Blue",
ATK_RELATION_LABEL_FOR=grandchild4}
{grandchild6 AtkAction,
AtkStateSet, role=ATK_ROLE_CHECK_BOX,
ATK_RELATION_LABELLED_BY=grandchild7}
{grandchild7 AtkText,
role=ATK_ROLE_LABEL, text="Green",
ATK_RELATION_LABEL_FOR=grandchild6}

[RFE: add ATK_RELATION_DESCRIBED_BY
and ATK_RELATION_DESCRIPTION_FOR to match MSAA/DHTML. Also, I thought we had
ATK_ROLE_FORM, but it seems not to be there. Did I miss something?]
































<form>
<label for="beverage">
Make a selection:
</label>
<select id="beverage">
<option>Water</option>
<option>Wine</option>
<option>Whiskey</option>
</select>
</form>









{parent role="html:form"}
{child AtkRelation,
role=ATK_ROLE_LABEL,
ATK_RELATION_LABEL_FOR}
{grandchild AtkText,
role=ATK_ROLE_TEXT,
text="Make a selection:",}
{child AtkAction,
AtkStateSet, AtkRelation,
AtkSelection, role=ATK_ROLE_COMBO_BOX,
ATK_RELATION_LABELLED_BY}
{grandchild role=ATK_ENTRY, AtkAction}
{grandchild role=ATK_LIST}
{great-grandchild AtkAction,
AtkStateSet, AtkText,
role=ATK_ROLE_LIST_ITEM, text="Water"}
{great-grandchild AtkAction,
AtkStateSet, AtkText,
role=ATK_ROLE_LIST_ITEM, text="Wine"}
{great-grandchild AtkAction, AtkStateSet,
AtkText, role=ATK_ROLE_LIST_ITEM,
text="Whiskey"}





















{parent role="html:form"}
{child AtkText,
AtkRelation,
role=ATK_ROLE_LABEL,
ATK_RELATION_LABEL_FOR,
text="Make a selection:"}
{child AtkAction,
AtkStateSet, AtkRelation, AtkText,
AtkSelection, role=ATK_ROLE_COMBO_BOX,
ATK_RELATION_LABELLED_BY,
text="??"}
{grandchild role=ATK_ENTRY, AtkAction}
{grandchild role=ATK_LIST, AtkText,
text="???"}
{great-grandchild AtkAction,
AtkStateSet, AtkText,
role=ATK_ROLE_LIST_ITEM, text="Water"}
{great-grandchild AtkAction,
AtkStateSet, AtkText,
role=ATK_ROLE_LIST_ITEM, text="Wine"}
{great-grandchild AtkAction, AtkStateSet,
AtkText, role=ATK_ROLE_LIST_ITEM,
text="Whiskey"}






















{parent role=ATK_ROLE_FORM?}
{child AtkText,
role=ATK_ROLE_LABEL,
ATK_RELATION_LABEL_FOR=child,
text="Make a selection:"}
{child AtkAction,
AtkStateSet, AtkSelection,
attr="html:role=select",
role=ATK_ROLE_COMBO_BOX,
ATK_RELATION_LABELLED_BY}
{grandchild,
AtkText,
  AtkStateSet=...SELECTABLE, SELECTED...,
attr="html:role=option",
role=ATK_ROLE_LIST_ITEM, text="Water"}
{grandchild,
AtkText,
  AtkStateSet=...SELECTABLE...,
attr="html:role=option",
role=ATK_ROLE_LIST_ITEM, text="Wine"}
{grandchild AtkText,
AtkStateSet=...SELECTABLE...,
role=ATK_ROLE_LIST_ITEM,
attr="html:role=option",
text="Whiskey"}

[note that because the entry field is not editable, but just displays the current
selection, I think it should not be exposed (especially since it represents a node
 which is not present in the HTML DOM. The list items need not implement AtkAction,
since the AtkSelection interface is used by the client to select among them.]




























Which sports do you like?

<form>
<label for="sports">
Which sports do you like:
<br>
<select id="sports"
multiple="multiple"
size="3">
<option>
<img src="beerglass.gif"
alt="Beer"/>
Baseball
</option>
<option>Basketball</option>
<option>Football</option>
</select>
</label>
</form>















{parent role="html:form"}
{child AtkRelation,
role=ATK_ROLE_LABEL,
ATK_RELATION_LABEL_FOR}
{grandchild AtkText,
role=ATK_ROLE_TEXT,
text/name="Which sports do you like:" }
{grandchild role="html:br"}
{grandchild AtkAction,
AtkStateSet, AtkRelation,
AtkSelection, role=ATK_ROLE_LIST,
ATK_RELATION_LABELLED_BY}
 {great-grandchild AtkAction, AtkStateSet,
role=ATK_ROLE_LIST_ITEM},
{gggg-child AtkImage,
name="Beer"}
{gggg-child AtkText,
text="Baseball"}
 {great-grandchild AtkAction, AtkStateSet,
AtkText, role=ATK_ROLE_LIST_ITEM,
text="Basketball"}
  {great-grandchild AtkAction, AtkStateSet,
AtkText, role=ATK_ROLE_LIST_ITEM,
text="Football"}























{parent AtkText,
role="html:form".
text="?"}
{child AtkText,
AtkRelation,
role=ATK_ROLE_LABEL,
ATK_RELATION_LABEL_FOR,
text="Which sports do you like:??"}
{grandchild role="html:br"}
{grandchild AtkAction,
AtkStateSet, AtkRelation, AtkText,
AtkSelection, role=ATK_ROLE_LIST,
ATK_RELATION_LABELLED_BY,
text="???"}
 {great-grandchild AtkAction,
AtkStateSet, AtkText,
role=ATK_ROLE_LIST_ITEM,
text="?Baseball"}
{gggg-child AtkImage,
name="Beer"}
 {great-grandchild AtkAction, AtkStateSet,
AtkText, role=ATK_ROLE_LIST_ITEM,
text="Basketball"}
  {great-grandchild AtkAction, AtkStateSet,
AtkText, role=ATK_ROLE_LIST_ITEM,
text="Football"}

























{parent role=ATK_ROLE_FORM?}
{child1 AtkText,
role=ATK_ROLE_LABEL,
ATK_RELATION_LABEL_FOR=child2,
text="Which sports do you like:\n"}
{child2 AtkObject,
accessible-name="sports" [not sure exposing the id is a good idea though],
AtkSelection,
AtkStateSet=...MULTISELECT...
attr="html:role=select",
role=ATK_ROLE_LIST,
ATK_RELATION_LABELLED_BY=child2}
{grandchild1,
AtkHyperText,
  AtkStateSet=...SELECTABLE, SELECTED...,
attr="html:role=option",
role=ATK_ROLE_LIST_ITEM, text="Baseball"}
{great-grandchild AtkImage, AtkHyperlink,
role=ATK_ROLE_IMAGE,
attr="html:role=img, link-type=image",
hyperlink-URI="beerglass.gif",
hyperlink-indices=[0,0]}
{grandchild2,
AtkText,
  AtkStateSet=...SELECTABLE...,
attr="html:role=option",
role=ATK_ROLE_LIST_ITEM, text="Basketball"}
{grandchild3 AtkText,
AtkStateSet=...SELECTABLE...,
role=ATK_ROLE_LIST_ITEM,
attr="html:role=option",
text="Football"}