Gecko info for Windows accessibility vendors

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.
  • 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 the Mozilla Accessibility Community ):

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 is 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.

the DOMenum { 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.

These relations can affect the calculation for the next next or previous item of a certain type. Here is an algorithm for iterating through the nodes, looking for an item of a particular type:

  1. Store a pointer to the start_item
  2. If the current item has a flows_to relation, follow that relation
  3. Otherwise, go to the next item in depth first search order
  4. If the current item matches your criteria, then return current_item
  5. If the current_item == start_item, return null (no item found)
  6. If the end has been reached, go back to the start if wrapping is desired, otherwise return null (no item found)
  7. Go to step 2

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>
DHTML: role="wairole:menubar"

Fires EVENT_MENUSTART and EVENT_MENUEND
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>
DHTML: role="wairole:alert"
Fires EVENT_ALERT
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
DHTML: role="wairole: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"

ROLE_TOOLTIP XUL: <tooltip> or tooltiptext attribute
ROLE_APPLICATION

Default role of root object of application
DHTML: role="wairole: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 editable frame via designMode.

ROLE_CHART Not supported. n/a
ROLE_DIALOG

XUL: <dialog>
DHTML: role="wairole:dialog"

accName() exposes the <title> of the current dialog.

ROLE_BORDER Not supported.
ROLE_GROUPING HTML: <fieldset>
XUL: <groupbox>
DHTML: role="wairole:group" or DHTML: role="wairole:radiogroup"
For a <fieldset> the name is exposed using the <legend>
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 <caption> first child of table or summary attribute
ROLE_COLUMNHEADER

XUL: tree column headers
HTML: <th>
DHTML: role="wairole:colheader"

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>
DHTML: role="wairole:gridcell"

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>
DHTML: role="wairole:listitem"
XUL: <listitem>
Sets STATE_SELECTED if the current listitem is selected.
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>
HTML: <label>
DHTML: role="wairole:label" or
role="wairole: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.

ROLE_TEXT

Normal web text uses no tag or element, uses STATE_READONLY
For editable text, that state is cleared.
XUL: <textbox>
HTML: <input type="text"> or <textarea>
DHTML: role="wairole:textfield" or
role="wairole:textarea"

Sets STATE_LINKED if within link.

Sets STATE_TRAVERSED if within visited link.

Sets STATE_HASPOPUP for autocomplete textfields

ROLE_PUSHBUTTON

XUL: <button>
HTML: <input type= "button"> or<button>
DHTML: role="wairole:button"

Sets STATE_HASPOPUP for buttons containing menus
ROLE_CHECKBUTTON

XUL: <checkbox>
HTML: <input type="checkbox">
DHTML: role="wairole:checkbox"

Fires EVENT_STATE_CHANGE when checkbox is toggled

ROLE_RADIOBUTTON

XUL: <radio>
HTML: <input type="radio">
DHTML: role="wairole:radio"

Fires EVENT_STATE_CHANGE when radiobutton is set

ROLE_COMBOBOX

XUL: <menulist>
HTML: <select size="1">
DHTML: role="wairole:combobox"

Fires EVENT_VALUECHANGE when current combobox option changes.
ROLE_DROPLIST Not supported. n/a
Role Supported? Unique features
ROLE_PROGRESSBAR

XUL: <progressmeter>
DHTML: role="wairole:progressbar"

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.

ROLE_DIAL Not supported n/a
ROLE_HOTKEYFIELD Not supported n/a
ROLE_SLIDER

XUL: <slider>
DHTML: role="wairole:slider"

Fires EVENT_VALUECHANGE when slider moves.

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>
DHTML: role="wairole:tabs"

"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 the wonderful 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:

 HRESULT get_URL  (/* [out] */ BSTR *url);  // Location of document
 HRESULT get_title (/* [out] */ BSTR *title); // From the <TITLE>
 HRESULT get_mimeType(/* [out] */ BSTR *mimeType); // For example text/html or text/plain
 HRESULT get_docType (/* [out] */ BSTR *docType); // From the <!DOCTYPE ..>
 HRESULT get_nameSpaceURIForID( // Translate namespace ID's from ISimpleDOMNode
   /* [in] */ unsigned short nameSpaceID, // calls into the actual namespace URI's
   /* [out] */ BSTR *nameSpaceURI);
 HRESULT put_alternateViewMediaTypes(/* [in] */ BSTR * commaSeparatedMediaTypes);
 // For example "aural, braille"

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. 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.
  • 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 contact the Mozilla Accessibility Community.