Each release of Mac OS X has brought increased support of "Universal Access" for users with disabilities. Universal Access is Apple's collective name for the Mac OS X technologies, features, and components that provide users with disabilities with access to Macintosh computers. Before Tiger, Apple implemented several features, such as magnification and inverting the image on the screen, and the ability to move the mouse using the keyboard. In Tiger, Apple has added VoiceOver, a full-featured screen reader and control interface. VoiceOver speaks screen activities, and provides keyboard access to every aspect of an application's user interface. Apple's VoiceOver technology not only opens up new doors for users with disabilities. It also helps parents, teachers, and anyone else who interacts or collaborates with users with disabilities. For Mac developers, making applications accessible to this audience is the smart thing to do, and it's easier now than ever before. This article will teach you how to fully implement support for accessibility through the VoiceOver interface in your Carbon application. VoiceOver TechnologyVoiceOver is a full-fledged accessibility interface, allowing users to control their computers using the keyboard and providing voice prompts. It is fully integrated into Mac OS X, and is available right from the very first installation screen, as well as from the login window. Because it is built in, VoiceOver also provides most applications with some functionality immediately. However, VoiceOver cannot do everything by itself; it uses information and features that applications provide in order to present the best interface to users. When VoiceOver is activated, it becomes the medium of communication between the user and your application, taking place of the mouse and screen. You navigate with the keyboard, and you "hear" the user interface instead of "seeing" it. You can find an overview of VoiceOver technology on the Mac OS X VoiceOver features page. Modifying Your Carbon Application to Work with VoiceOverYour application is partially VoiceOver-enabled automatically—the HIToolbox does that for you. However, partially enabled applications can sometimes give extraneous or misleading information to VoiceOver, which passes this information on to the user. Supporting VoiceOver is much easier if you've already adopted HIViews—otherwise you are setting yourself up for a lot of work. In this article, we assume that you have already adopted Carbon Events and HIViews. Note: This article describes modifications necessary to use VoiceOver with Carbon applications. Cocoa developers should refer to the Cocoa Accessibility documentation for information on using Accessibility features in their applications. Or see the article, Enabling Accessibility in Your Cocoa Application. The key data structure that VoiceOver uses is the "Accessibility Hierarchy" (AH). The Accessibility Hierarchy is a thin, toolbox-independent method of representing the user interface. Cocoa and Carbon each implement an AH, and VoiceOver communicates with your application through the AH. Each object in the AH corresponds to a visual item in the user interface, only some of which the user can interact with. For example, the user can interact with a button, but not with painted text, although both will probably have entries in the AH. The HIToolbox builds the hierarchy automatically, but you can augment it (or change it radically) at runtime for your application. In Carbon, the Accessibility Hierarchy is composed of objects of type If you are using standard user interface controls, much of the work is already done for you. The standard controls respond to the accessibility Carbon Events, so, in general, they "do the right thing". However, there is some information that the control cannot know; your application has to supply it.
For example, if you are writing a browser, you will probably have a "Back" button in a toolbar. If the button shows the title "Back", then
VoiceOver can read that to the user because VoiceOver will automatically return a Note: The word "back" is not capitalized. It is recommended that descriptions not contain capital letters, except for acronyms or formal names. Adding full support for VoiceOver typically involves four steps:
The rest of this article will examine these steps in more detail. Adding VoiceOver Support to Your Custom HIViewsIf you have custom There are several Carbon Events that your view needs to handle. In general, these events can be sent for the entire view, or for
any "parts" of the view. You can find complete descriptions in the Note: For detailed information on handling and returning information from Carbon Accessibility Events, see the Carbon Accessibility Reference. Child NavigationThe Carbon Events in the child navigation group are:
Attribute ManipulationThe attribute manipulation Carbon Events are:
ActionsThe Carbon Events in the actions group are:
Customizing the Application HierarchyNow that you have updated your custom HIViews to return accessibility information, it is time to work on your application. Developers often display a static text control near another control (such as an edit text control) to alert the user to the purpose of the control.
However, a user who is visually impaired may not be able to read the static text control, or may not be able to associate the text with the control.
For example, in Mail's composition window, there is a text field with the word "To:" placed immediately to the left.
Visually, the text field is adorned with a title, but the text field's title is provided by another element.
In this situation, you can use Some user interface elements, such as panes that group controls (enabling them to move or resize together, for example) are not interactive,
and have no physical presence on the screen. To the end user, these elements do not exist; they are merely a developer convenience.
If you have controls like this, you should mark them as "ignored" in the AH. Carbon provides the Note that a customized The ImageMapView sample demonstrates several aspects of customization:
For the ImageMapView application, that's all we need to do! Supporting Accessibility for non-HIView User Interface ElementsEven if you are using Carbon Events and HIViews everywhere you can, there is still probably a portion of your user interface where you are not using HIViews. For example, a flowchart application will probably not use HIViews to display and manipulate individual elements in a flow chart. Similarly, a word processing program would not create an HIView for each paragraph, sentence, or word in a document. But that doesn't mean that users don't want to navigate or manipulate those parts of your application. Apple has provided the AXCanvas example to help you in these types of situations. This example is available in the /Developer/Examples/Accessibility folder. Exploring the Accessibility HierarchyApple supplies a tool called "Accessibility Inspector", located in the /Developer/Applications/Utilities/Accessibility Tools folder. The Accessibility Inspector displays the AH of the user interface element the mouse is currently over. The display also includes the supported attributes and actions for that UI Element. You can either explore the hierarchy by moving the mouse, or press cmd-F7 to lock the display on a particular element. For example, if you hover the mouse over the green button ("+") in the upper left of any window, you will see a display similar to the following: <AXApplication: "DragPeeker X"> <AXWindow: "DragPeeker X"> <AXButton> Attributes: AXRole: "AXButton" AXRoleDescription: "zoom button" AXSubrole: "AXZoomButton" AXParent: "<AXWindow: "DragPeeker X">" AXWindow: "<AXWindow: "DragPeeker X">" AXTopLevelUIElement: "<AXWindow: "DragPeeker X">" AXPosition: "x=50 y=26" AXSize: "w=14 h=16" AXEnabled: "true" Actions: AXPress - press The description tells us where the item lives in the AH, that it is a button control, and a description of what it does. In this case, the "+" button "zooms". If the
user interface element has an Figure 1: Accessibility Inspector Locked on Dialog You can look at each of the attributes of the button; if any of them are settable you can set them (note there are no settable attributes for the "+" button). Attributes you can set are marked with "(W)" at the end of the name. You can also navigate the AH from this point, either moving up (to the window or application) or down (to the button's children). If the item supports any actions, you can perform them here—if you click on the Perform button, it will have exactly the same effect as clicking on the button. In this case, the window will zoom. You can navigate up or down the hierarchy using the goto popup menu. An example of this is shown below. Finally, if you click on the "Highlight" checkbox, the area of the screen that the item occupies will be colored a pale red. Let's look at a more complicated example, from TextEdit. The screenshot in Figure 2 was taken while the mouse was over the Center button in TextEdit's tool bar: Figure 2: TextEdit Application Accessibility Inspector displays the following information for the Center button: <AXApplication: "TextEdit"> <AXWindow: "Untitled"> <AXScrollArea> <AXRuler> <AXGroup> <AXGroup> <AXRadioGroup> <AXRadioButton> Attributes: AXValue: "false" AXRoleDescription: "radio button" AXParent: "<AXRadioGroup>" AXWindow: "<AXWindow: "Untitled">" AXHelp: "Center" AXSize: "w=25 h=25" AXRole: "AXRadioButton" AXPosition: "x=249 y=78" AXTitle: "(null)" AXEnabled: "true" AXFocused: "false" AXDescription: "align center" AXTopLevelUIElement: "<AXWindow: "Untitled">" Actions: AXPress - press As you can see, the segment control identifies itself as a radio button. That is because its behavior is exactly the same as a radio button group—only one item can be selected at once. Clicking on one element in the control causes the other elements to be deselected. Currently, it is not selected (AXValue: false), but it is enabled (AXEnabled: true) and its help text is "Center". The help text appears when the mouse cursor hovers over the element, and it can also be read to the user; it's a bit brief in this example, but much better than nothing. The AXTitle attribute is to be used when the element's title is visually represented with text, for example, an "OK" button. The AXDescription attribute is used when the element's title is not represented visually. For example, the "back" button in a web browser, which is represented visually by an arrow. TextEdit has a more complicated AH, so there is more here to navigate. Press cmd-F7 to display the Locked on dialog. If you select the goto menu, you can select the parent AXRadioGroup (for example). From there, you can see that the radio group has four children, which is what we expect, given that the segmented control has four options. We can navigate all the way up to the TextEdit application, if we choose. With the Accessibility Inspector, you can check out your Accessibility Hierarchy and compare it to the on-screen controls. This way, you can be sure that your controls have the correct accessibility information, attributes, and actions. Apple also provides a tool called "Accessibility Verifier", located in the /Developer/Applications/Utilities/Accessibility Tools folder. The Accessibility Verifier can look at your AH and find common errors, such as missing roles or descriptions. It's quite handy for checking out your AH. However, it finds lots of different errors, including a few that are caused by bugs in the Carbon Toolbox. This sometimes makes it hard to determine which errors are yours, and which ones come from the Carbon Toolbox. Once you are convinced that your AH is correct, all that is left is to turn on VoiceOver, and try out your application with VoiceOver. For More Information
Posted: 2006-06-12 |