Accessibility/AT-Windows-API
<< Back to Accessibility Home Page
Contents
- 1 Propose
- 2 Definitions
- 3 Windows Applications Based on the Gecko Layout Engine
- 4 How to Find the Content Window and Load the Document
- 5 MSAA Support: IAccessible Methods
- 6 MSAA Support: IAccessible Events and Unique ID's
- 7 MSAA Features We Do Not Support
- 8 Intentional Differences with Internet Explorer
- 9 MSAA Role Support
- 10 Enhancing Performance on the Client End via IEnumVARIANT
- 11 Avoiding Memory Leaks
- 12 Additional DOM Support
- 13 Keyboard User Interface and API
- 14 Beyond HTML: Other Types of Web Content
- 15 Questions or Comments?
Propose
This FAQ explains how makers of Windows screen readers, voice dictation packages and magnification software can support Gecko-based software. The base of our support for these products is MSAA (Microsoft Active Accessibility), external readonly DOM support, and the keyboard API/user interface.
Definitions
Here are some basic definitions that you'll need for this document to make sense:
- Gecko:
- The rendering engine for Firefox, Thunderbird, Nvu, Mozilla Seamonkey and other applications. Gecko is the internal engine that Mozilla uses to render any kind of web content. It supports HTML, XHTML, Cascading Style Sheets (CSS) and the Document Object Model (DOM).
- Microsoft Active Accessibility (MSAA)
- an API devised by Microsoft so that accessibility aids can track what's going on inside the user interface of any software package that supports it. If you seriously need to understand MSAA, you'll need to read the docs on MSDN and play with the sample apps and code that come with MSAA SDK 1.3. (I recommend SDK 1.3 because the MSAA SDK 2.0 doesn't come with the source code to the testing tools. The other differences are not important).
- DOM: Document Object Model
- This is the W3C's specification for how web content is exposed to Javascript and other languages. It covers content, style and events. Inside the Gecko process, code has full access to DOM APIs. However, exposing the entire DOM to external software packages is quite involved, partially because changes to the DOM in Firefox must occur on the main thread. We have chosen a subset of readonly methods in the DOM needed for assistive technology vendors. Events such as focus changes must be tracked through MSAA events, rather than DOM events.
- XUL: eXtensible User-interface Language
- The XML-based language used by Firefox and Mozilla to develop the UI. Similar to HTML in that it can be combined with CSS and Javascript to make powerful applications. Contains more desktop-style widgets than HTML and follows a box layout model, rather than being text-flow based.
- AJAX: Asynchronous JavaScript And XML
- AJAX is a method of building interactive web applications that process user requests, user actions immediately in real time, unlike an HTTP request, during which users must wait for a whole page to reload or for a new page to load. Data is therefore stored and retrieved dynamically much faster.
- Roles, states and events
- please read the MSAA documentation on MSDN if you are unfamiliar with these. in general we abbreviate by removing redundant words. For example, we may say EVENT_ALERT instead of the full EVENT_SYSTEM_ALERT.
MSAA tree vs. DOM tree - what's the relation?
The MSAA tree and the DOM tree are parallel structures, although the MSAA tree is a subset of the DOM tree. QueryService()
can be used to switch between the interfaces (IAccessible, ISimpleDOMDocument, ISimpleDOMNode and ISimpleDOMText). If there is no MSAA node for a DOM node, or vice-versa, QueryService()
will return null.
Anything that is focusable or conveys important information about the structure of the document is exposed in the MSAA tree of IAccessibles.
Windows Applications Based on the Gecko Layout Engine
Gecko is a rendering engine that Mozilla, Netscape and other new browsers use. Gecko can render a variety of content, not just HTML and supports key web standards such as Cascading Style Sheets, Javascript and the W3C DOM. Gecko also handles the users keystrokes and mouse clicks. Gecko is the core architecture that we are adding accessibility to, in order to support basic accessibility in all applications that are based on it.
Embedded Clients (support MSAA)
Embedded clients use Gecko only in the content window, at the moment for HTML and generic XML only. They typically use standard Windows controls for their user interface -- the area outside of the client content window, plus the context menu.
-
MFCEMBED
testing client: This is a very simple package, great for testing basic HTML accessibility with your products and the Gecko rendering engine. Contact Aaron Leventhal - aaronleventhal@ m o o n s e t . net for a copy. - K-Meleon: a light, ultra-fast and more advanced (fully configurable) Gecko-based web browser available on the Windows platform
XUL-Based Clients (support MSAA)
XUL-based clients make full use of the Gecko architecture, not only for HTML content, as well as for menus, dialogs and the entire user interface via an XML language called XUL (eXtensible User-interface Language). None of the user interface contains standard Windows controls -- not even the menus! This is done to ensure a common look and feel across all supported platforms, and to allow for different skins (appearances).
- Firefox (please use version 1.1 alpha builds or later)
- Thunderbird (please use version 1.1 alpha builds or later)
- Mozilla Seamonkey (please use 1.8 alpha builds or later)
How to Find the Content Window and Load the Document
Screen readers need to find the content window so that they know where to start grabbing the MSAA tree, in order to load the current document into a buffer in their own process. The content window always has the class MozillaContentWindowClass.
In total, Gecko supports the following window classes:
- MozillaUIWindowClass - root UI window, at the root of the window hierarchy
- MozillaContentWindowClass -- root document window
- MozillaContentFrameWindowClass - root of a subdocument created by a <frame> or <iframe> element
- MozillaHiddenWindowClass - ignore these windows, they are used to help manage other windows
- MozillaWindowClass - general filler window, a catch all
Starting in Firefox 2, however, you should begin switching your code to use NAVRELATION_EMBEDS. Going forward, this may be the only way to efficiently find the content area, as Mozilla will begin to become a windowless application, with an exception for plugins which create their own window.
When you see the content window receive focus, first check the role. If it is ROLE_PANE or ROLE_DOCUMENT then this should be treated as a document for the default modality of the screen reader. If it is a ROLE_APPLICATION, ROLE_DIALOG or ROLE_ALERT then stay in focus tracking mode -- there is no need to parse the document. In addition, if it is a ROLE_ALERT, a screen reader should treat it as a message box -- that is, to read the entire contents. These roles can occur on content because of the new Accessible DHTML technology which allows the author to specify the type of document or container.
Once you know that you have a document, go up the ancestor chain of windows until you see a MozillaContentWindowClass or a MozillaUIWindowClass. If it is a content window, you may use AccessibleObjectFromWindow() to get the root IAccessible for the content, and begin traversing the tree from there.
Gecko also helps determine when to load a new window by firing two EVENT_STATE_CHANGE's on the root ROLE_DOCUMENT accessible -- the first state change indicates the document pane is now busy loading. The second state change indicates the document pane has finished. When handling the event, use get_accState() to check the STATE_BUSY flag. When the document has finished loading the busy flag will be cleared.
MSAA Support: IAccessible Methods
To use MSAA with Gecko, you'll need the tools and docs that come with the Active Accessibility 2.0 SDK Tools. The method AccessibleObjectFromWindow()
will get you the root IAccessible corresponding to the top level window. Hold on to this root IAccessible, and use it to walk through the entire tree of IAccessible's.
IAccessible methods that we support:
- get_accParent
- get_accChildCount
- get_accChild
- get_accName
- get_accValue
- get_accDescription
- get_accRole
- get_accState
- get_accFocus
- get_accDefaultAction
- accLocation
- accSelect
- accHitTest
- accDoDefaultAction
- accNavigate
- get_accKeyboardShortcut
MSAA Support: IAccessible Events and Unique ID's
What MSAA events do we support?
- EVENT_FOCUS is fired for focus changes on any kind of focusable object
- EVENT_STATECHANGE is used in check boxes, radio buttons, text fields, combo boxes and list boxes. It's also used in the root pane object to show when the STATE_BUSY flag changes from loading new content.
- EVENT_SCROLLINGEND is used to indicate when a document has scrolled, even if only 1 line. Gecko fires this event when the scrolling is finished, rather than fire excessive events.
- EVENT_SCROLLINGSTART is fired when the user has jumped to a named anchor within the page. The event is fired on the first accessible object in the part of the document that has been jumped to.
- EVENT_MENUPOPUPSTART and EVENT_MENUPOPUPEND are fired when XUL menus are opened or closed.
- EVENT_MENUSTART and EVENT_MENUEND are fired when the XUL menubar is activated or deactivated.
- EVENT_VALUECHANGE is fired for sliders, progress meters and other objects who's get_accValue() may change.
- EVENT_SHOW, EVENT_HIDE and EVENT_LOCATIONCHANGE are fired for the caret object.
- EVENT_REORDER is fired on an object whenever its children change. EVENT_SHOW and EVENT_HIDE may also be fired with the reorder event, for the child who's visibility changed. The show and hide events are not fired on every IAccessible when a new subtree of IAccessibles changes visibility -- only the top IAccessible. The exception is progress meters, which are guaranteed to fire EVENT_SHOW and EVENT_HIDE events when they are displayed or hidden.
- EVENT_ALERT is fired when an object of ROLE_ALERT appears or changes. This should indicate to a screen reader to read the contents of the alert (it may be a container who's descendents should be read).
- EVENT_SELECTION is fired on children of single selection containers along with the EVENT_FOCUS as selection/focus move together in that case.
- EVENT_SELECTIONWITHIN is fired on multi selection containers when the current selection changes within. In addition, EVENT_SELECTIONADD and EVENT_SELECTIONREMOVE are fired on the the child who's selection changed.
How to track where the event happened, within your own offscreen model
Ordinary zero-indexed child IDs are not practical for representing events. The problem is that the child ID system that is used by MSAA doesn't work well when you have a deep tree of objects in a window. It would be impractical to number all of the nodes in a document starting at 0, because whenever a node is inserted or removed it would be computationally very expensive to renumber things. So, the Firefox childID handed back from events is based on an algorithm that uses the pointer value of the related internal DOM node. This computed child ID for events is always a negative value, unique to the IAccessible firing the event
These negative childID's from events can be used with AccessibleObjectFromEvent(), or on the root accessible of a window with any IAccessible method that takes a VARIANT, such as get_accChild().
Because screen readers usually cache an entire document's worth of data, it can be extremely useful for them to receive a child ID that helps them correlate back to a known object. We provide support for this technique via ISimpleDOMNode::get_nodeInfo(), which returns a uniqueID for any IAccessible that can be cached in the internal model. When an event is received, the negative childID should match one of these cached uniqueID's, if the entire document has been stored and kept current. Keeping an internal cache current means getting new subtrees of IAccessibles whenever an EVENT_REORDER is received, indicating important changes have invalidated part of the model.
MSAA Features We Do Not Support
No one has yet asked for the following features (if you need something, please contact Aaron Leventhal ):
IAccessible methods that we don't currently support:
- get_accHelp
- get_accHelpTopic
- put_accName
- put_accValue
- We do not currently support the Visual Basic (IDispatch) bindings for IAccessible.
- We do not currently support directional navigation via accNavigate()
- We do not currently support scroll bars as IAccessible objects, although we do support EVENT_SCROLLINGEND and ISimpleDOMNode::ScrollTo(), explained below.
- We do not currently support STATE_MOVEABLE, STATE_SIZEABLE or STATE_MARQUEED.
- We do not currently support ROLE_SYSTEM_ROW, although Internet Explorer doesn't either, and the reason seems apparent. It is not obvious where the ROLE_SYSTEM_ROW should exist in the tree when the HTML rowspan attribute is used to combine to cells in different rows. There are currently two techniques for parsing tables: 1) use accLocation() to get the coordinates for each cell and feed that into an algorithm that builds up your own table data structure, or 2) use ISimpleDOMNode and parse the table
- See below for the complete list of roles and notes about what we support
Intentional Differences with Internet Explorer
For the most part, where we support an MSAA feature, we have tried to duplicate Internet Explorer's use of it. Please let us know if you find any differences not listed here:
Accessible Relations are Supported
The accNavigate() method can be used with new constants defined for Gecko. The results are always returned via VT_DISPATCH.
enum { NAVRELATION_LABEL_FOR = 0x1002 };
enum { NAVRELATION_DESCRIPTION_FOR = 0x100f };
These two relations can be used on object to determine what form control is being labelled or desribed.
enum { NAVRELATION_LABELLED_BY = 0x1003 };
enum { NAVRELATION_DESCRIBED_BY = 0x100e };
These two relations are they inverse; they can be used on form controls. If the form control has an accName, you can get the IAccessible that it was labelled by in order to get more formatting information. It is also useful to check for a description.
Note that the label and description relations may be used to prevent redundant information from being presented by the screen reader, since the label and description can occur both on their own, and in the name or description fields of an IAccessible.
enum { NAVRELATION_DEFAULT_BUTTON = 0x100d };
When used within an HTML form or a XUL dialog, the NAVRELATION_DEFAULT_BUTTON relation will return the IAccessible for the default button.
enum { NAVRELATION_EMBEDS = 0x1009 };
This relation is used on the root accessible object for a top level Mozilla window, corresponding to what's returned for OBJID_CLIENT for that window. It points to the accessible object corresponding to the root of content in that window. This relation is very useful for finding the content quickly, and will be the proper method for finding content in Firefox 3 and beyond.
enum { NAVRELATION_CONTROLLED_BY = 0x1000 };
enum { NAVRELATION_CONTROLLER_FOR = 0x1001 };
These two relations show what form controls may dynamically change areas of the document, in response to user changes in the form controls themselves. Both controlled_by and controller_for are set in markup from the single dynamic content accessibility dynamic content aaa:controls attribute. The inverse controlled_by relation is automatically calculated.
enum { NAVRELATION_FLOWS_TO = 0x1006 };
enum { NAVRELATION_FLOWS_FROM = 0x1007 };
These two relations allow the reading flow to break out of the normal DOM flow. Both flows_to and flows_from are set in markup from the single dynamic content accessibility aaa:flowsto relation -- the inverse flow_from relation is automatically calculated.
Checkable, Required and Invalid States are Supported
Gecko defines three state constants using previously unused states:
const unsigned long STATE_CHECKABLE = STATE_MARQUEED; // Useful on menuitem, listitem // and treeitem. Indicates that the absence of STATE_CHECKED should be spoken as // "unchecked", and that EVENT_STATE_CHANGE will be fired in the event that the // checkbox is toggled.
const unsigned long STATE_REQUIRED = STATE_ALERT_LOW; // Used on form controls // to indicate that this field must be filled out to submit the form
const unsigned long STATE_INVALID = STATE_ALERT_HIGH; // Used on form controls to // indicate the the field does not currently have a legal value
const unsigned long STATE_??? = STATE_ALERT_MEDIUM; // Reserved for future use.
Document Structure Exposed in MSAA Tree
BSTR roles are used for important roles that have not been defined by Microsoft. When the role is retrieved in a VARIANT returned from get_accRole, check to see if variant.vt == VT_BSTR. If it is, than variant.bstrVal contains the role string.
The role string may be an HTML tag name followed by comma, space and the namespace of the current element. In most current cases the namespace can be ignored, but it may become important in the future. The following HTML tags are exposed as BSTR's:
abbr, acronym, blockquote, dd, dl, dt, form, frame, h1, h2, h3, h4, h5, h6, iframe, q, tbody, tfoot, thead
In addition, an HTML list uses the bullet
BSTR role to expose bullets and numbers that are automatically inserted into the formatting by Gecko. In addition, ROLE_LIST with STATE_READONLY and ROLE_LISTITEM are used to expose the list structure. This makes it important to check the STATE_READONLY flag when encountering a ROLE_LIST, because the HTML list form element also uses ROLE_LIST, but without STATE_READONLY set.
Positional Descriptions are Supported
The accDescription field is overriden for the following roles:
ROLE_LISTITEM, ROLE_MENUITEM, ROLE_RADIOBUTTON, ROLE_PAGETAB and ROLE_OUTLINEITEM
For everything other than outline item, the positional description is in the form "n of m" where n is an integer indicating the position within other similar objects in a group, and m represents the number of objects in that group. For example, "3 of 5" indicates the 3rd object out of 5.
For outline item, more information is provided, in a format that reads "L#, n of m with c" where # represents the level that the outline item is at, and c represents the number of children. The n of m position relates to the position within the current outline level.
Finally, true descriptions are now exposed with the text "Description: " prepending the description. This makes it clear that the description is truly intended to be read. Neither "Description:" or "of" in the above strings is ever localized, so they should be parsed out.
DHTML Accessibility is Supported
This means that you may encounter roles that are not typically in HTML content. Be prepared for new combinations of roles and states in content, such as ROLE_SLIDER, ROLE_PROGRESSBAR and STATE_REQUIRED. In addition, check the STATE_FOCUSABLE bit on tables, which indicates a traversable DHTML spreadsheet. Please see the DHTML accessibility documentation page for more information on this topic.
IAccessibles Persist
Unless the document changes, retrieving the IAccessible more than once for the same object will return the same IAccessible*. The uniqueID will remain the same as well. If the document does change, EVENT_REORDER, EVENT_HIDE and EVENT_SHOW are used to indicate where the changes will occur. Because of the persistence, relations and events can be mapped within an assistive technology's internal model.
Page Loading is Tracked via STATE_CHANGE events
When a new document is about to be loaded, an EVENT_STATE_CHANGE occurs on the root ROLE_DOCUMENT object for a window. The STATE_BUSY flag is now set for the root pane object.
Once the new page is ready to be displayed and traversed via its IAccessible tree, the old content window is destroyed, and a new window is created. Next, another EVENT_STATE_CHANGE is fired for the new root ROLE_DOCUMENT object for the window, with its STATE_BUSY flag cleared.
MSAA Role Support
Role | Supported? | Unique features |
---|---|---|
ROLE_TITLEBAR | Supported automatically by MS Windows | |
ROLE_MENUBAR | XUL: <menubar/> | Fires EVENT_MENUSTART and EVENT_MENUEND |
DHTML: role="wairole:menubar" | ||
ROLE_SCROLLBAR | not supported | n/a |
ROLE_GRIP | not supported | n/a |
ROLE_SOUND | not supported | n/a |
ROLE_CURSOR | not supported | n/a |
ROLE_CARET | supported for caret | Fires EVENT_SHOW, EVENT_HIDE, EVENT_LOCATIONCHANGE |
ROLE_ALERT | XUL: <browsermessage/> | Fires EVENT_ALERT |
DHTML: role="wairole:alert" | ||
XForms: <message/>, <alert/>, <help/> | ||
ROLE_WINDOW | Supported automatically by MS Windows | |
ROLE_CLIENT | XUL: <browser/> | |
HTML: <frame> or <iframe> | ||
ROLE_MENUPOPUP |
DHTML: role="wairole:menu" |
Fires EVENT_MENUPOPUPSTART, EVENT_MENUPOPUPEND |
ROLE_MENUITEM | XUL: <menuitem/> | Sets STATE_CHECKED for radio or checkbox menuitem types
Accelerator key comes in accName after a \t (TAB) character. For example, "Open\tCtrl+O" |
DHTML: role="wairole:menuitem" | ||
XForms: <item/> of minimal <select1/> in XHTML document | ||
ROLE_TOOLTIP | XUL: <tooltip> or tooltiptext attribute | |
ROLE_APPLICATION |
Default role of root object of application |
accName() exposes the <title> of the current pane. |
Role | Supported? | Unique features |
ROLE_DOCUMENT | Default role for root object of document DHTML: role="wairole:document" |
Sets STATE_READONLY indicates it is a normal document, otherwise we're in an editor. Sets STATE_BUSY when a new document is loading in this space. Fires EVENT_STATE_CHANGE when busy flag is set or cleared due to document load starting or finishing. accValue() exposes the URL of the current pane. accName() exposes the <title> of the current pane. |
ROLE_PANE | The first child of a <frame> or <iframe> |
accValue() exposes the URL of the current document. accName() exposes the <title> of the current pane. Sets STATE_READONLY unless it's an [../../editor/midasdemo/ editable frame via designMode]. |
ROLE_CHART | Not supported. | n/a |
ROLE_DIALOG | XUL: <dialog/> | accName() exposes the <title> of the current dialog. |
DHTML: role="wairole:dialog" | ||
ROLE_BORDER | Not supported. | |
ROLE_GROUPING | HTML: <fieldset> | For a <fieldset> the name is exposed using the <legend> |
XUL: <groupbox> | ||
DHTML: role="wairole:group" or role="wairole:radiogroup" | ||
XForms: compact <select/>, minimal <select1/> in XUL document, <input/> of xsd:gMonth/xsd:gDay types | ||
ROLE_SEPARATOR | XUL: <separator/> | |
HTML: <hr> | ||
DHTML: role="wairole:separator" | ||
ROLE_TOOLBAR | XUL: <toolbar> DHTML: role="wairole:toolbar" |
|
ROLE_STATUSBAR | XUL: <statusbar> | |
Role | Supported? | Unique features |
ROLE_TABLE | HTML: <table> DHTML: role="wairole:grid" (In this case STATE_FOCUSABLE is set) |
accName is supported via |
ROLE_COLUMNHEADER |
XUL: tree column headers |
|
ROLE_ROWHEADER | DHTML: role="wairole:rowheader" | |
ROLE_COLUMN | Not supported. | |
ROLE_ROW | Not supported. See the section Intentional Differences with IE | |
ROLE_CELL |
HTML: <td> |
Sets STATE_READONLY in normal table. Sets STATE_FOCUSABLE in data grids and spreadsheets Clears STATE_READONLY in spreadsheets. Sets STATE_SELECTED in spreadsheets when a cell has selection. |
ROLE_LINK | XUL: <label class="text-link"> -- this should be changed, we need a real <link> widget for XUL HTML: <a> and <area> |
Sets STATE_LINKED if it is pointing somewhere. Sets STATE_TRAVERSED if link has been visited. Sets STATE_SELECTABLE if it is an HTML named anchor accValue() exposes the URL that is pointed to |
ROLE_HELPBALLOON | Not supported. | n/a |
ROLE_CHARACTER | Not supported. | n/a |
ROLE_LIST | XUL: <listbox> | |
HTML: <select size=""> where size > 1 -- STATE_READONLY is off HTML: <ol> or <ul> -- STATE_READONLY is on |
||
DHTML: role="wairole:list" | ||
ROLE_LISTITEM | HTML: <li>, <option> or <optgroup> | Sets STATE_SELECTED if the current listitem is selected. |
DHTML: role="wairole:listitem" | ||
XUL: <listitem/> | ||
ROLE_OUTLINE | DHTML: role="wairole:tree" | |
ROLE_OUTLINEITEM | DHTML: role="wairole:treeitem" |
Sets STATE_COLLAPSED if has children that are not currently visible. Sets STATE_EXPANDED if has children that are currently visisted. Sets STATE_SELECTED if the current tree item is selected. Fires EVENT_STATE_CHANGE when tree item expands/collapses |
ROLE_PAGETAB | XUL: <tab> DHTML: role="wairole:tab" |
|
ROLE_PROPERTYPAGE | XUL: <tabpanel> DHTML: role="wairole:tabpanel" |
|
ROLE_INDICATOR | Not supported. | |
ROLE_GRAPHIC | XUL: <image> HTML: <img> |
Sets STATE_LINKED if within link. Sets STATE_TRAVERSED if within visited link. |
ROLE_STATICTEXT | XUL: <label> or <description> | Supports NAVRELATION_LABEL_FOR and NAVRELATION_DESCRIPTION_FOR via accNavigate().
The accName is an accumulation of the descendents' accNames, so may be considered redundant with them. The accName is also reflected in the accName of a form control that this labels, which is a good reason to check NAVRELATION_LABEL_FOR. |
HTML: <label> | ||
DHTML: role="wairole:label" or role="wairole:description" | ||
XForms: <output/>, <label/> | ||
ROLE_TEXT | Normal web text uses no tag or element, uses STATE_READONLY For editable text, that state is cleared. |
Sets STATE_LINKED if within link.
Sets STATE_TRAVERSED if within visited link. |
ROLE_ENTRY | HTML: <input type="text"> or <textarea> | Sets STATE_HASPOPUP for autocomplete textfields |
XUL: <textbox> | ||
DHTML: role="wairole:textfield" or role="wairole:textarea" | ||
XForms: default <input/> | ||
ROLE_PUSHBUTTON | XUL: <button> | Sets STATE_HASPOPUP for buttons containing menus |
HTML: <input type= "button"> or<button> | ||
DHTML: role="wairole:button" | ||
XForms: <trigger/>, <submit/> | ||
ROLE_CHECKBUTTON | XUL: <checkbox> | Fires EVENT_STATE_CHANGE when checkbox is toggled |
HTML: <input type="checkbox"> | ||
DHTML: role="wairole:checkbox" | ||
XForms: <item/> of full <select/> <input/> of boolean type | ||
ROLE_RADIOBUTTON | XUL: <radio> | Fires EVENT_STATE_CHANGE when radiobutton is set |
HTML: <input type="radio"> | ||
DHTML: role="wairole:radio" | ||
XForms: <item/> of full <select1/> | ||
ROLE_COMBOBOX | XUL: <menulist> | Fires EVENT_VALUECHANGE when current combobox option changes. |
HTML: <select size="1"> | ||
DHTML: role="wairole:combobox" | ||
XForms: <select1/> in XHTML document | ||
ROLE_DROPLIST | XForms: xsd:date <input/> | |
Role | Supported? | Unique features |
ROLE_PROGRESSBAR | XUL: <progressmeter/> | Fires EVENT_VALUECHANGE when progressbar moves by at least 3%
Fires EVENT_SHOW and EVENT_HIDE directly on ROLE_PROGRESSBAR when it appears/disappears as well as on ancestor container that visibility may have changed on. |
DHTML: role="wairole:progressbar" | ||
ROLE_DIAL | Not supported | n/a |
ROLE_HOTKEYFIELD | Not supported | n/a |
ROLE_SLIDER | XUL: <slider> | Fires EVENT_VALUECHANGE when slider moves. |
DHTML: role="wairole:slider" | ||
XForms: <range/> | ||
ROLE_SPINBUTTON | DHTML: role="wairole:spinbutton" | Fires EVENT_VALUECHANGE when spinbutton moves |
ROLE_DIAGRAM | <svg> | Indicates the root of an SVG tree |
ROLE_ANIMATION | Not supported. Animated images use ROLE_GRAPHIC with STATE_ANIMATED. | |
ROLE_EQUATION | <math> (in MathML namespace) | Indicates the root of a MathML tree. |
ROLE_BUTTONDROPDOWN | Not supported, STATE_HASPOPUP used with ROLE_BUTTON instead | |
ROLE_BUTTONMENU | Not supported, STATE_HASPOPUP used with ROLE_BUTTON instead | |
ROLE_BUTTONDROPDOWNGRID | Supported for XUL <colorpicker> | |
ROLE_PAGETABLIST |
XUL: <tab> |
|
"abbr", "acronym", "blockquote", "dd", "dl", "dt", "form", "frame", "h1", "h2", "h3", "h4", "h5", "h6", "iframe", "q", "tbody", "tfoot", "thead" | HTML tag mirrors the role string | |
"bullet" | Indirectly created for bullets when <ol> or <ul> used to create an HTML list | |
"abbr", "acronym", "blockquote", "form", "frame", "h1", "h2", "h3", "h4", "h5", "h6", "iframe", "q", "tbody", "tfoot", "thead" | Created from the identical HTML markup | No name |
Role | Supported? | Unique features |
Enhancing Performance on the Client End via IEnumVARIANT
Whenever you get an IAccessible, you can QI it to IEnumVARIANT. If that succeeds, then it has children. You can then get the number of children via IAccessible::get_accNumChildren(), then allocate an array of VARIANT's to hold the children, and call IEnumVARIANT::Next() to get all the children in one call. The VARIANT's we provide will always be VT_DISPATCH.
Using IEnumVARIANT in this way is much faster than getting the children via get_accChild() or accNavigate(). See MSDN for more information.
Avoiding Memory Leaks
It is the assistive technology's responsibility to watch for system events that indicate when windows are being destroyed, and to release all IAccessibles related to that window.
To help web developers in that regard, there is Memory Leak monitor, a Firefox 1.5+ extension from David Baron, which warns chrome and extension developers about one particular type of memory leak. It warns when chrome windows close but leave native code pointing at their JavaScript objects. This typically happens for things like observers, timer callbacks, and (in Firefox 1.5 and earlier) event listeners, and is one of the most common causes of leaks in chrome and extension code.
Additional DOM Support
There are a number of things available in the parsed HTML or XML of a document that MSAA will not tell you.
To solve this problem, we provide access to the content DOM for Gecko documents, through two interfaces:
- ISimpleDOMNode gives you the actual parsed structure of a document, by node.
- ISimpleDOMText supports scrolling and rectangular bounds information on a character by character basis
- ISimpleDOMDocument contains basic document information, such title, URL, doctype and mime type.
Compiling the .idl Files
To use these interfaces, you'll need to get the ISimpleDOMNode.idl, ISimpleDOMText.idl and ISimpleDOMDocument.idl file. You must make a header files for them, by running these commands:
MIDL ISimpleDOMNode.idl
MIDL ISimpleDOMText.idl
MIDL ISimpleDOMDocument.idl
That will generate ISimpleDOMNode.h and ISimpleDOMDocument.h, which define the interfaces. It will also create ISimpleDOMNode_i.c and ISimpleDOMDocument_i.c, which contain the necessary IID constants.
ISimpleDOMNode
To get to the ISimpleDOMNode interface for an object, you start with an IAccessible*, and then you QueryService to the ISimpleDOMNode*:
IServiceProvider *pServProv = NULL; pAccessible->QueryInterface(IID_IServiceProvider, (void**)&pServProv); ISimpleDOMNode *pSimpleDOMNode; if (pServProv) { const GUID refguid = {0x0c539790, 0x12e4, 0x11cf, 0xb6, 0x61, 0x00, 0xaa, 0x00, 0x4c, 0xd6, 0xd8}; HRESULT result = pServProv->QueryService(refguid, IID_ISimpleDOMNode, (void**)&pSimpleDOMNode); if (SUCCEEDED(hresult) && pSimpleDOMNode != NULL) { /* This is a Mozilla node! Use special ISimpleDOMNode methods described in ISimpleDOMNode.idl. */ } }
The get_nodeInfo
method is used to get basic information about a node such as the tag name and namespace ID, node type (see ISimpleDOMNode.idl for definitions), node value (text held in the node), a unique ID for use in tracking where events occur, and the number of children. The namespace ID is meaningless until you get the namespace URI for it, through the ISimpleDOMDocument interface (see below).
HRESULT get_nodeInfo( /* [out] */ BSTR *nodeName, // For elements, this is the tag name /* [out] */ short *nameSpaceID, /* [out] */ BSTR *nodeValue, /* [out] */ unsigned int *numChildren, /* [out] */ unsigned int *uniqueID, // see description of unique ID's // in above section on events /* [out] */ unsigned short *nodeType);
The get_attributes
method returns the set of attribute, value pairs for a given node, as well as the namespace ID for each attribute. The return value numAttribs specifies the number of attributes for this node, and the last 3 parameters return 3 arrays corresponding to attribute name, namespace ID, and attribute value.
HRESULT get_attributes( /* [in] */ unsigned short maxAttribs, /* [out] */ BSTR *attribNames, /* [out] */ short *nameSpaceID, /* [out] */ BSTR *attribValues, /* [out] */ unsigned short *numAttribs);
A variation on this method is get_attributesForNames
, which lets turns the attribNames array into an [in] parameter, letting you specify only those attributes you're interested in. This helps minimize the cost of marshalling for those times in which you're interested in only a few attributes per node.
HRESULT get_attributesForNames( /* [in] */ unsigned short numAttribs, /* [in] */ BSTR __RPC_FAR *attribNames, /* [in] */ short __RPC_FAR *nameSpaceID, /* [out] */ BSTR __RPC_FAR *attribValues);
The get_computedStyle
method is used to find out the cumulative, computed results for all style rules applied to a node. The return value numStyleProperties specifies the number of style properties for this node, and the last 2 parameters return 2 arrays corresponding to style property name and style property value. Another [in] parameter, useAlternativeMediaProperties, indicates whether you want style information for the default media type (usually screen), or a set of alternative media types specified in nsISimpleDOMDocument::set_alternateViewMediaType(mediaTypeString)
. See the W3C's website for a list of official media type name . Unfortunately, at this time the argument useAlternateView
is ignored.
HRESULT get_computedStyle( /* [in] */ unsigned short maxStyleProperties, /* [in] */ boolean useAlternateView, // If TRUE, returns properties for // media as set in nsIDOMDocument:: // set_alternateViewMediaTypes /* [out] */ BSTR *styleProperties, /* [out] */ BSTR *styleValues, /* [out] */ unsigned short *numStyleProperties);
A variation on this method is get_computedStyleForProperties
, which lets turns the styleProperties array into an [in] parameter, letting you specify only those style properties you're interested in. This helps minimize the cost of marshalling for those times in which you're interested in only a few style properties per node.
HRESULT get_computedStyleForProperties( /* [in] */ unsigned short numStyleProperties, /* [in] */ boolean useAlternateView, // If TRUE, returns properties for // media as set in nsIDOMDocument:: // set_alternateViewMediaTypes /* [in] */ BSTR *styleProperties, /* [out] */ BSTR *styleValues);
To scroll the document in order make a specific element visible in the window, use scrollTo(boolean placeTopLeft)
. If the parameter placeTopLeft
is TRUE the document will be scrolled so that the element is placed in the top left corner of the window. If placeTopLeft
is FALSE, the document will only be scrolled if the element is not already visible, or the document will be scrolled the minimum amount to make the element visible anywhere within the current window.
HRESULT scrollTo([in] boolean placeTopLeft);
You can also get to any other node by traversing the ISimpleDOMNode structure. The DOM content tree is a superset of the MSAA tree. In other words, you can always QueryInterface from an IAccessible to an ISimpleDOMNode, but often not the other way around.
HRESULT get_parentNode (/* [in] */ ISimpleDOMNode *newNodePtr); HRESULT get_firstChild (/* [in] */ ISimpleDOMNode *newNodePtr); HRESULT get_lastChild (/* [in] */ ISimpleDOMNode *newNodePtr); HRESULT get_previousSibling(/* [in] */ ISimpleDOMNode *newNodePtr); HRESULT get_nextSibling (/* [in] */ ISimpleDOMNode *newNodePtr); HRESULT get_childAt (/* [in] */ unsigned childIndex, /* [out] */ ISimpleDOMNode **newNodePtr);
Next we provide a convenience method for getting the actual HTML within a DOM subtree. This only applies if the node is HTML.
HRESULT get_innerHTML([out, retval] BSTR *innerHTML);
Finally we provide a method for getting the current ISO 639 language code, such as "en" for English or even possible "en-cockney" for the British Cockney dialect.
HRESULT get_language([out, retval] BSTR *language);
Please look at the ISimpleDOMNode.idl file for parameter types and the definitions of the node type constants.
ISimpleDOMText
DOM nodes that are text nodes support ISimpleDOMText. This extension is useful if you need to work on a character by character basis, whereas IAccessible provides only node by node support. Text nodes must be leaf nodes, so there is no need to check for this interface if the current node has any MSAA or DOM children. Text nodes always support ISimpleDOMNode as well as ISimpleDOMText.
Here are the methods for ISimpleDOMText:
// Includes all DOM whitespace; IAccessible::get_accName does not HRESULT get_domText(BSTR *domText); // Bounding rect clipped to window HRESULT get_clippedSubstringBounds([in] unsigned int startIndex, [in] unsigned int endIndex, [out] int *x, [out] int *y, [out] int *width, [out] int *height); // Bounding rect unclipped HRESULT get_unclippedSubstringBounds([in] unsigned int startIndex, [in] unsigned int endIndex, [out] int *x, [out] int *y, [out] int *width, [out] int *height); // Scroll to this part of the subsstring HRESULT scrollToSubstring([in] unsigned int startIndex, [in] unsigned int endIndex); // Get the current font being used -- this is better than using // the ISimpleDOMNode CSS property methods, because it provides // a single font name, rather than a comma delineated list of possibilities HRESULT fontFamily([out] BSTR *fontFamily);
ISimpleDOMDocument
There is one ISimpleDOMDocument interface for each XML or HTML document in Gecko, which you can use to get important information global to the document. If a given node's get_nodeType method returns NODETYPE_DOCUMENT, then you know you can QueryInterface to an ISimpleDOMDocument. The root accessible can also always be QueryInterface'd to an ISimpleDOMDocument.
Here are the methods for ISimpleDOMDocument:
// Location of document HRESULT get_URL(/* [out] */ BSTR *url); // From the <TITLE> HRESULT get_title(/* [out] */ BSTR *title); // For example text/html or text/plain HRESULT get_mimeType(/* [out] */ BSTR *mimeType); // From the <!DOCTYPE ..> HRESULT get_docType(/* [out] */ BSTR *docType); // Translate namespace ID's from ISimpleDOMNode HRESULT get_nameSpaceURIForID( /* [in] */ unsigned short nameSpaceID, // calls into the actual namespace URI's /* [out] */ BSTR *nameSpaceURI); // For example "aural, braille" HRESULT put_alternateViewMediaTypes(/* [in] */ BSTR *commaSeparatedMediaTypes);
Keyboard User Interface and API
Fortunately, Gecko uses the standard keyboard API's for each supported platform.
For a large number of keyboard commands, we emulate Internet Explorer's keyboard shortcuts. Our keyboard plan describes our current design and future possibilities.
Beyond HTML: Other Types of Web Content
- You may have heard of some content types beyond HTML, and want to know if Gecko based products will support them:
- DHTML and AJAX: Gecko and other browsers have long supported dynamic content, where the page appearance changes because of JavaScript. This can be used to create the appearance of desktop-style widgets like menus, spreadsheets and tree views which HTML lacks. Or, it can be used to completely change content on the fly, without loading a new page. Previously it was not posible to make this accessible, but Firefox 1.5 supports Accessible DHTML, which allows authors to make advanced widgets and web applications accessible.
- MathML: an XML dialect used to display full math notation on web pages. Here's the ongoing Mozilla project to support MathML . We do not currently have plans to support MSAA for MathML - we will likely suggest use of the external DOM for this, because MSAA simply does not have the right semantics in it to support mathematics. MathML support is currently built into Firefox.
- SVG : Scalable Vector Graphics. Essentially W3C's XML-based version of Flash - mixes well with other markup based content, supports the DOM and has accessibility features. Mozilla's SVG Project has been through several stalls and rebirths -- SVG will probably become more of a priority if other well known browsers support it. We will not know how, or whether, we will support SVG accessibility until a better implementation comes along. Firefox 1.5 supports SVG. Potentially it can make use of the same namespaced role and state attributes as DHTML accessibility, but it may require more powerful author-definable relationships.
- XForms: XForms is the future of online forms as envisioned by the W3C. Drawing on other W3C standards like XML Schema, XPath, and XML Events, XForms tries to address some of the limitations with the current HTML forms model. One of the key features of XForms is accessibility. Firefox 1.5 supports XForms by XForms extension. XForms accessibility is implemented for Firefox 3.
- XUL: The XML-based language used by Firefox and Mozilla to develop the UI. Similar to HTML in that it can be combined with CSS and Javascript to make powerful applications. Contains more desktop-style widgets than HTML and follows a box layout model, rather than being text-flow based. In the future more standalone applications will use XUL via XULRunner.
Questions or Comments?
Please discuss accessibility issues on the Mozilla-Accessibility mailing list. You can also e-mail me (Aaron Leventhal) directly at aaronleventhal@moonset.net .