This page is currently under construction. This developer's guide lays out general guidelines that assistive technology (AT) developers can use in developing live region support. This guide was written from an ATK/AT-SPI point of view as part of the Orca Live Region Support project. However, many of the concepts were also used during the development of FireVox, an AT using IAccessible2.
For more information about Live Regions, please read the ARIA properties spec or the live region report to learn about ARIA Live Region markup and the Live Region API Support document for the latest Firefox API with regards to Live Regions.
As always, we're open to questions and suggestions for changes in community forums.
The heart of any live region support module is the priority queue. It is responsible for queuing messages derived from live region events, where priority is determined by chronological order and the live politeness properties. In addition to the standard priority queue methods, additional methods will need to be implemented that purge the queue based on one of the priority criterion. The "purge by timestamp" method will be used to remove old messages that are no longer deemed relevant while "purge by politeness" is used to satisfy the ARIA live politeness specification. The later method will be explained in detail below.
The table for web page mutation event types lists the two major event types associated with live regions, namely text-changed and object changed events. Both will be discussed in detail below.
The object changed events are slightly different in AT-SPI and IAccessible2. In AT-SPI, the object changed event are called object:children-changed events because the event is triggered on the parent of the object. The actual object that change can then be found in the event.any_data field. In IAccessible2, the EVENT_OBJECT_* events are triggered on the actual object that changed.
The object changed events can be further subdivided into object addition and removal events. In AT-SPI, this is accomplished by appending ":add" or ":remove" to the event string. In IAccessible2, there are two separate event types, namely EVENT_OBJECT_SHOW and EVENT_OBJECT_HIDE.
The text changed events are quite similar in AT-SPI and IAccessible2 with both having an insert and delete or removal events. The text changed event type in AT-SPI has a similar scheme as the object:children-changed events. In this case, the root event string is object:text-changed with ":delete" and ":insert" being appended to complete the event type. In IAccessible2, there are two distinct event types - IA2_EVENT_TEXT_REMOVED and IA2_EVENT_TEXT_INSERTED.
The text associated with an AT-SPI text changed event is directly in the event object. The event.any_data field holds the entire text string while event.detail1 is the start index while event.detail2 is the text string length. In IAccessible2, IAccessibleText::get_oldText and IAccessibleText::get_newText are used to acquire the text and offsets.
Text Changed Events
Certain web page mutation events, such as adding to a list, trigger both an object changed and a text changed event. Both events should not be acted upon or double announcements would result. Instead, all text changed events should be examined for the presence of an embed character. If one is present, the text changed event should be discarded because an object changed event will follow.
Filtering User Actions
This paragraph describes object properties and event naming schemes that are used to help an AT determine if an event is an actual live region event or is the result of user action.
Filtering for Performance
The most significant difference between AT-SPI and IAccessible2 is that AT-SPI is an inter-process communication service while IAccessible2 runs in process. As a result, care must be taken in an AT-SPI based application to minimize performance degradation by only acting on events that are truly live regions. These "non-live" events may be events originating from the chrome, user interaction in the chrome or document, document loading events, or real live region events from hidden tabs. With the goal of eliminating the "non-live" events, some sort of event filtering logic must be employed. The following is a list of potential filtering techniques:
- The "event-from-input" object attribute can be used to filter events that were triggered by user action.
- The ":system" (or lack thereof) can be used to filter events that are system generated. (AT-SPI only)
- A global variable can be set in a document:load:complete event listener and reset in a object:state-changed:busy listener. This variable can then be used to quickly determine if an event was triggered by the document being loaded.
- An event containing an object that does not have state VISIBLE is probably from a hidden tab.
- An event containing an object that has state SELECTABLE is not a live region.
- An event containing an object that has the attribute "container-live" is a live region. However, many web sites do not have proper ARIA markup so this cannot be used by itself.
- An event containing an object that has an attribute "tag:xul*" is not a live region.
- An event that has an object that is not a descendant of the document frame is not a live region.
This table describe the object attributes associated with a live region event. The following are guidelines on how to implement each
This property determines the interruption policy or politeness level for the event and can have values of "off", "polite", "assertive" and "rude". This property, along with an event's time stamp, determine the priority of a message within the priority queue. The following describes actions that should be taken for an event with the given politeness level:
- off: No action should be taken. The event should be filtered out as early as possible to prevent performance degradation.
- polite: A message should be derived from the event and added to the queue.
- assertive: The queue should be purged of 'polite' messages and the new message should be added to the queue. Speak should not be interrupted.
- rude: The queue should be purged of 'polite' and 'assertive' messages and the new message should be added to the queue. Current utterances should be allowed to finish but the 'rude' messages should be output as soon as possible.
The atomic property determines if a live region change should be presented on it's own or if an AT should present the entire region. If atomic is set to "true", it means that the region must be presented as a whole while atomic="false" (default) indicates that the region can stand on it's own.
The text offsets associated with a text changed event are used when supporting this property. The offsets can be acquired directly in a text changed event object in AT-SPI and through the use of IAccessibleText::get_oldText and IAccessibleText::get_newText in IAccessible2. When atomic is set to "false", the start index and end index/run length are used as given. The result being that only the change will be presented. When atomic is set to "true", the entire region should be presented. In this case the start index is 0 and the end index/run length is the length of the text - 1.
The channel property defines two channels - 'main' and 'alert'. It was originally intended to give web developers a means to force a live region message to go to a separate output device. For instance, a 'main' channel message might go to the speech generator while an 'alert' channel message might be sent to a Braille device. However, the channel property is also significant for single output applications that rely on speech output only. In this case, 'main' channel messages are queued according to the 'live' property and 'alert' channel messages bypass the queue and are output immediately. The rationale being that alerts are meant to quickly grab the user's attention in the event of a major issue, such as a system/server failure.