Accessible Toolkit Checklist
What needs to be done when building new toolkits
Original author: Aaron Leventhal - a a r o n @ m o o n s e t . n e t
The Work
When implementing a new toolkit it's important to:
- Implement standard keyboard behavior, which can vary from
platform to platform.
- Expose your UI - a way for assistive technologies such as
screen readers, screen magnifiers and voice dictation software to
understand your software.
- Provide theme compatibility with the operating system, at
least as an option.
Some low vision users will be running your software with high contrast
or large font themes.
- Go beyond section
508. Implement true usability for everyone, and make your
toolkit follow the guidelines for each platform.
The Approaches
There are two basic kinds of toolkits, which each provide different
challenges when implementing accessibility:
- Native widget toolkits, like Eclipse and wxWindows, already have some
accessibility built-in. These toolkits
wrap the widgets implemented by the OS with an consistent API for each
platform.
Since the individual widgets predominately come from the operating
system, they already implement
standard keyboard commands and follow the operating system's visual
theme. Also, assistive technologies already understand native widgets
so it is only necessary to implement MSAA support for custom controls.
However, be aware that the wrapping layer will introduce accessibility
bugs, and thus you will need to test extensively and fill in the holes.
You will also need to provide
a way for custom and owner drawn controls to easily accessibility API
support, as wxWindows
does.
There will be custom and owner drawn controls -- there always are. For
example, lists of checkboxes are implemented in Windows with images of
checked and unchecked checkboxes.
- Owner drawn toolkits, like XUL and Flash's
Flex UI framework use few or no
native widgets. These toolkits need to have accessibility implemented
from the ground up, and get nothing for free in terms of keyboard, API
or OS-theme support. In this case, adding a complete or even a partial
accessibility solution is major work, and will require more than one
full time person as well as cooperating from Windows assistive
technology vendors when parts of your MSAA solution isn't working.
Often these kinds of toolkits don't use a separate window for each
control; in that case remember to generate a unique 32 bit child ID for
each control so that the MSAA event system can call back
for the right IAccessible for each event.
The Checklist
This checklist is currently only for Microsoft Windows. I would like
to add information for Linux and OS X, as well
as fill in any missing pieces.
Please email me at a a r o n @ m
o o n s e t . n e t, if have questions or something to
contribute.
- Dialogs/windows/general
- Escape key cancels dialogs and refocuses the previously focused
on the parent window.
- Alt+F4 closes windows, similar to Escape but even works on
dialogs without Cancel button
- Alt+space opens window menu with Restore, Move, Size, Minimize,
Maximize, Close
- The Move and Size options must be usable with the arrow keys on
the keyboard
- In windows, initial focus goes to first focusable
widget that is not a clickable tabbed property sheet label - Making
tab order definable. Default tab order should be in document order.
- Tab order must wrap, not have invisible items in tab order
- Dynamically added items must not corrupt the tab cycle or make
it disorderly
- Tab cycle must be identical backwards and forwards
- The F6 and Shift+F6 key combinations should cycle through panes
in a window
- Making focus visible on any widget, and focus must always be
visible
- Shift+F10 or context menu key should work like right click on
focused item, and context menu should show just under and to the right
of the current focus. On Mac OS X, ctrl+space is used to bring up the
context menu.
- Most widgets (like checkboxes) can have a label outside of
themselves, which should focus the widget when clicked on, or when its
mnemonic is pressed. The system should require these labels to be
created/associated with each widget, not as a separate static text with
no tie to the widget. The MSAA support needs to know what label goes
with what widget.
- MSAA support: expose window with ROLE_DIALOG, unless it's
already the standard dialog window class #32770. If you don't, some
screen readers
won't automatically read the dialog when it receives focus. Expose
status bars with ROLE_STATUSBAR, unless they already use
the standard window class msctls_statusbar32. Make sure that
parent-child relationships are exposed correctly in each window's MSAA
tree
- General MSAA support
- Focus events
- Handling event callbacks, which requires a unique ID for each
non-windowed child of every widget that can be focused or have any
other event associated with it. For example, a unique child ID would be
required for each tree item
- Supporting the most important basic IAccessible events
- get_accParent: Get the parent of an IAccessible.
- get_accChildCount: Get the number of children of an
IAccessible.
- get_accChild: Get the child of an IAccessible.
- get_accName: Get the "name" of the IAccessible, for example
the name of a button, checkbox or menu item. This is one reason why a
label must be created together with each widget, rather than separately.
- get_accValue: Get the "value" of the IAccessible, for example
a number in a slider, a URL for a link, the text a user entered in a
field.
- get_accRole: Get an enumerated value representing what this
IAccessible is used for, for example. is it a link, static text,
editable text, a checkbox, or a table cell, etc.
- get_accState: a 32 bit field representing possible on/off
states, such as focused, focusable, selected, selectable, visible,
protected (for passwords), checked, etc.
- get_accKeyboardShortcut: What is the keyboard shortcut for
this IAccessible (underlined alt+combo mnemonic)
- get_accFocus: Which child is focused?
- get_accSelection: Which children of this item are selected?
- accLocation: Get the x,y coordinates, and the height and
width of this IAccessible node.
- accNavigate: Navigate to the first/last child, previous/next
sibling, up, down, left or right from this IAccessible. [important, but
no need to implement up/down/left/right]
- accDoDefaultAction: Perform the action described by
get_accDefaultAction.
- Supporting the basic MSAA states on every item: unavailable,
focused, readonly, offscreen, focusable
- To avoid extra work, utilize implementing
an MSAA Server
- Mnemonics
- Ability to define in XML for any widget with a text label (via
attribute or a preceding char in label)
- Automatically define mnemonics for all standard common dialogs
(like Yes/No confirmations and Retry/Exit error dialogs)
- Support mnemonics in dialogs created via method calls
- Layout engine - drawing underline under correct letter
- Events - making keystrokes do the right thing
- MSAA support, via IAccessible's get_accKeyboardShortcut
- Menus
- Arrow keys, Enter, Escape
- Alt alone enters main menu
- After leaving menus, focus is restored to where it was
- Modified and unmodified mnemonics
- MSAA support (including focus events, menu start and end
events, radio and checkbox menu items)
- Static text and Group boxes
- MSAA support
- Buttons
- Tab, arrow, unmodified letter mnemonics
- Require and support text labels for buttons with images, can
be same as tooltip
- Space key activates button
- Enter key activates focused button (thus current button, not
default button shows dark border when a different button is focused)
- When button has a popup available by clicking on it, the
Enter key or space bar should also activate the popup
- Toolbars and toolbar buttons are not focusable, but we should
expose the tooltip. If possible, make the tooltip automatically append
text for the keyboard shortcut associated with it.
- MSAA support, including the haspopup state
- Default buttons
- Ability to define in XML
- Enter key fires it, but not when another widget has focus that
needs the Enter key
- Layout engine - drawing dark border dynamically when
the currently focused widget does not need the Enter key - Events -
making keystrokes do the right thing
- MSAA support (default state)
- Links
- Enter key activates link (thus default button no longer shows
dark border when link is focused)
- MSAA support, including linked and traversed states, and
accessible value that holds destination URL
- Text fields - single and multiple line
- It's probably best to use native widgets for these, otherwise
accessibility support will be quite difficult
- Tab should always focus the next item, not insert a tab, unless
there's a really good reason and another way to navigate
- Always use system selection color, otherwise screen reader
won't read the text
- Make sure the caret is never blinking when focus is not in text
field
- Handle standard editing keys, such as arrow keys, home, end,
pageup, pagedown, ctrl+left/right, shifted keys for selection, delete,
ctrl+delete, backspace, ctrl+backspace, ctrl+a, ctrl+b, ctrl+c, ctrl+i,
ctrl+u, ctrl+x, ctrl+v, ctrl+[shift]+z
- In multiline text field, Enter key inserts new line (thus
default button no longer shows dark border when multiline text field is
focused)
- In autocomplete text fields, make sure the autocomplete popup
doesn't receive actual or MSAA focus unless an up/down arrow is
pressed, and don't use the default system highlight color in the list
itself unless it really has focus
- In autocomplete text fields, make sure that the delete or
backspace key removes all auto completed selected text.
- In autocomplete text fields, make sure that the left or right
arrow closes the popup and starts moving through the text letter by
letter
- MSAA support, including accessible value that holds text,
protected for password fields and readonly for read-only fields
- Checkboxes
- Space bar to toggle
- MSAA support, including checkbox state and statechange event
- Radio buttons
- Only the selected radio button is in the tab order
- The other radio buttons can be selected and focused with
up/down arrow.
- The focused radio button is always selected, and vice versa
- Keyboard and MSAA support must still work correctly when
radio button labels have textfields, combo boxes or other controls as
part of their prompts.
- MSAA support, including checkbox state and statechange event
- Sliders
- Keyboard support for moving slider: arrow keys, home, end,
PgUp, PgDn
- MSAA support including ROLE_SLIDER, accessible value, value
change events
- Progress bars
- MSAA support including accessible name, value, name and value
change events
- Tabbed "property sheet" dialogs
- Ctrl+[shift]+tab or Ctrl+PgUp/PgDn to switch tabs
- Tabs can be focused, and then left/right arrow to switch
- First click on a tab switches to it, second click focuses it
- MSAA support
- Lists and combo boxes
- When a list is tabbed to, select the first item if nothing else
is already selected
- F4, Alt+down or alt+up toggle a combo box open and closed
- Escape closes combo box if it was open (be careful not to have
it cancel entire dialog)
- Up/down arrow key navigation. Shift+up and shift+down move and
extend the selection.
- Typing letter or several letters to navigate (same letter goes
to each item starting with that, different letters go to first item
starting with that entire string).
- Multiple selection is possible with Ctrl+arrow to move focus
without selecting, then space to select item, shift+space to select to
current point or control+space to toggle selection of current item
- Shift+F10 or context menu key to bring up context menu for
current item. Generate a context menu event. On Mac OS X, ctrl+space is
used to bring up the context menu.
- Space bar toggles checkboxes
- For listboxes, use owner drawn list items to show a different
highlight color when the list is not focused. If you don't the list
focus will not be apparent, and screen readers may read the selected
list item when they shouldn't. For unfocused lists, use a lighter color
highlight to show a non-focused state. For autocomplete lists, use the
system color offset by 1, so that it looks active but the list items
don't get echoed while they user's trying to simply type and edit.
- MSAA support, including accessible selection, selectable,
multiselectable and extselectable states, and statechange events for
checkbox children
- Tree view navigation
- When a tree view is tabbed to, select the first item if nothing
else is already selected
- Up/down arrow key navigation
- Left arrow to first collapse a branch, then move to parent
- Right arrow to first expand a branch, then move to first child
- Multiple selection is possible with Ctrl+arrow to move focus
without selecting, then space to select item, shift+space to select to
current point or control+space to toggle selection of current item
- Typing letter or several letters to navigate (similar to list
support for this)
- Shift+F10 or context menu key to bring up context menu for
current item (On OS X ctrl+space is used to bring up context menu).
- Space bar toggles checkboxes
- The enter key should activate an item if double clicking would
do so
- MSAA support, including accessible selection, exposing current
level and position in list, alternative text for informative or
interactive images, selectable, multiselectable and extselectable
states, statechange events for expanding/collapsing and toggling of
checkbox children
- Mac OS X difference: option+left and option+right should do
deep expand/collapse
- Mac OS X difference: user should be able to select multiple
rows and expand them with one keystroke. After the expansion, the
multiple (now discontiguous) selection should remain.
- Support for MS Windows settings
- When high contrast checkbox is set (in accessibility control
panel, SPI_GETHIGHCONTRAST), or when user selects a "Native" skin
option in your software, then get all look and feel from current OS
skin.
- The high contrast theme can be toggled dynamically with
LeftAlt+LeftShift+printscreen
- Expose the SPI_GETSCREENREADER flag to XML/scripts so that apps
can alter behavior
- Use system highlight color where possible for item selection,
but never use that exact color in more than 1 place at a time,
otherwise screen reader will read everything with that color whenever
highlight changes
- Pay attention to SPI_GETCARETWIDTH for the correct width of the
caret
- Pay attention to 'route mouse pointer to default button' setting
- It's possible that the user wants mnemonics hidden except when
the alt key is pressed. This can be supported through
SPI_GETKEYBOARDCUES and SPI_GETMENUUNDERLINES