/**************************************************************************** ** ** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). ** All rights reserved. ** Contact: Nokia Corporation (qt-info@nokia.com) ** ** This file is part of the documentation of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL$ ** No Commercial Usage ** This file contains pre-release code and may not be distributed. ** You may use this file in accordance with the terms and conditions ** contained in the Technology Preview License Agreement accompanying ** this package. ** ** GNU Lesser General Public License Usage ** Alternatively, this file may be used under the terms of the GNU Lesser ** General Public License version 2.1 as published by the Free Software ** Foundation and appearing in the file LICENSE.LGPL included in the ** packaging of this file. Please review the following information to ** ensure the GNU Lesser General Public License version 2.1 requirements ** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. ** ** In addition, as a special exception, Nokia gives you certain additional ** rights. These rights are described in the Nokia Qt LGPL Exception ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. ** ** If you have questions regarding the use of this file, please contact ** Nokia at qt-info@nokia.com. ** ** ** ** ** ** ** ** ** $QT_END_LICENSE$ ** ****************************************************************************/ /*! \group accessibility \title Accessibility Classes */ /*! \page accessible.html \title Accessibility \ingroup frameworks-technologies \tableofcontents \section1 Introduction Accessibility in computer software is making applications usable for people with disabilities. This could be achieved by providing keyboard shortcuts, a high-contrast user interface that uses specially selected colors and fonts, or support for assistive tools such as screen readers and braille displays. An application does not usually communicate directly with assistive tools but through an assistive technology, which is a bridge for exchange of information between the applications and the tools. Information about user interface elements, such as buttons and scroll bars, is exposed to the assistive technologies. Qt supports Microsoft Active Accessibility (MSAA) on Windows and Mac OS X Accessibility on Mac OS X. On Unix/X11, support is preliminary. The individual technologies are abstracted from Qt, and there is only a single interface to consider. We will use MSAA throughout this document when we need to address technology related issues. In this overview document, we will examine the overall Qt accessibility architecture, and how to implement accessibility for custom widgets and elements. \section1 Architecture Providing accessibility is a collaboration between accessibility compliant applications, the assistive technology, and the assistive tools. \image accessibilityarchitecture.png Accessibility compliant applications are called AT-Servers while assistive tools are called AT-Clients. A Qt application will typically be an AT-Server, but specialized programs might also function like AT-Clients. We will refer to clients and servers when talking about AT-Clients and AT-Servers in the rest of this document. We will from now on focus on the Qt accessibility interface and how it is implemented to create Qt applications that support accessibility. \section2 Accessibility in Qt These classes provide support for accessible applications. \annotatedlist accessibility When we communicate with the assistive technologies, we need to describe Qt's user interface in a way that they can understand. Qt applications use QAccessibleInterface to expose information about the individual UI elements. Currently, Qt provides support for its widgets and widget parts, e.g., slider handles, but the interface could also be implemented for any QObject if necessary. QAccessible contains enums that describe the UI. The description is mainly based on MSAA and is independent of Qt. We will examine the enums in the course of this document. The structure of the UI is represented as a tree of QAccessibleInterface subclasses. You can think of this as a representation of a UI like the QObject tree built by Qt. Objects can be widgets or widget parts (such as scroll bar handles). We examine the tree in detail in the next section. Servers notify clients through \l{QAccessible::}{updateAccessibility()} about changes in objects by sending events, and the clients register to receive the events. The available events are defined by the QAccessible::Event enum. The clients may then query for the object that generated the event through QAccessible::queryAccessibleInterface(). Three of the enums in QAccessible help clients query and alter accessible objects: \list \o \l{QAccessible::}{Role}: Describes the role the object fills in the user interface, e.g., if it is a main window, a text caret, or a cell in an item view. \o \l{QAccessible::}{Action}: The actions that the clients can perform on the objects, e.g., pushing a button. \o \l{QAccessible::}{Relation}: Describes the relationship between objects in the object tree. This is used for navigation. \endlist The clients also have some possibilities to get the content of objects, e.g., a button's text; the object provides strings defined by the QAccessible::Text enum, that give information about content. The objects can be in a number of different states as defined by the \l{QAccessible::}{State} enum. Examples of states are whether the object is disabled, if it has focus, or if it provides a pop-up menu. \section2 The Accessible Object Tree As mentioned, a tree structure is built from the accessible objects of an application. By navigating through the tree, the clients can access all elements in the UI. Object relations give clients information about the UI. For instance, a slider handle is a child of the slider to which it belongs. QAccessible::Relation describes the various relationships the clients can ask objects for. Note that there are no direct mapping between the Qt QObject tree and the accessible object tree. For instance, scroll bar handles are accessible objects but are not widgets or objects in Qt. AT-Clients have access to the accessibility object tree through the root object in the tree, which is the QApplication. They can query other objects through QAccessible::navigate(), which fetches objects based on \l{QAccessible::}{Relation}s. The children of any node is 1-based numbered. The child numbered 0 is the object itself. The children of all interfaces are numbered this way, i.e., it is not a fixed numbering from the root node in the entire tree. Qt provides accessible interfaces for its widgets. Interfaces for any QObject subclass can be requested through QAccessible::queryInterface(). A default implementation is provided if a more specialized interface is not defined. An AT-Client cannot acquire an interface for accessible objects that do not have an equivalent QObject, e.g., scroll bar handles, but they appear as normal objects through interfaces of parent accessible objects, e.g., you can query their relationships with QAccessible::relationTo(). To illustrate, we present an image of an accessible object tree. Beneath the tree is a table with examples of object relationships. \image accessibleobjecttree.png The labels in top-down order are: the QAccessibleInterface class name, the widget for which an interface is provided, and the \l{QAccessible::}{Role} of the object. The Position, PageLeft and PageRight correspond to the slider handle, the slider groove left and the slider groove right, respectively. These accessible objects do not have an equivalent QObject. \table 40% \header \o Source Object \o Target Object \o Relation \row \o Slider \o Indicator \o Controller \row \o Indicator \o Slider \o Controlled \row \o Slider \o Application \o Ancestor \row \o Application \o Slider \o Child \row \o PushButton \o Indicator \o Sibling \endtable \section2 The Static QAccessible Functions The accessibility is managed by QAccessible's static functions, which we will examine shortly. They produce QAccessible interfaces, build the object tree, and initiate the connection with MSAA or the other platform specific technologies. If you are only interested in learning how to make your application accessible, you can safely skip over this section to \l{Implementing Accessibility}. The communication between clients and the server is initiated when \l{QAccessible::}{setRootObject()} is called. This is done when the QApplication instance is instantiated and you should not have to do this yourself. When a QObject calls \l{QAccessible::}{updateAccessibility()}, clients that are listening to events are notified of the change. The function is used to post events to the assistive technology, and accessible \l{QAccessible::Event}{events} are posted by \l{QAccessible::}{updateAccessibility()}. \l{QAccessible::}{queryAccessibleInterface()} returns accessible interfaces for \l{QObject}s. All widgets in Qt provide interfaces; if you need interfaces to control the behavior of other \l{QObject} subclasses, you must implement the interfaces yourself, although the QAccessibleObject convenience class implements parts of the functionality for you. The factory that produces accessibility interfaces for QObjects is a function of type QAccessible::InterfaceFactory. It is possible to have several factories installed. The last factory installed will be the first to be asked for interfaces. \l{QAccessible::}{queryAccessibleInterface()} uses the factories to create interfaces for \l{QObject}s. Normally, you need not be concerned about factories because you can implement plugins that produce interfaces. We will give examples of both approaches later. \section2 Enabling Accessibility Support By default, Qt applications are run with accessibility support enabled on Windows and Mac OS X. On Unix/X11 platforms, applications must be launched in an environment with the \c QT_ACCESSIBILITY variable set to 1. For example, this is set in the following way with the bash shell: \snippet doc/src/snippets/code/doc_src_qt4-accessibility.qdoc environment Accessibility features are built into Qt by default when the libraries are configured and built. \section1 Implementing Accessibility To provide accessibility support for a widget or other user interface element, you need to implement the QAccessibleInterface and distribute it in a QAccessiblePlugin. It is also possible to compile the interface into the application and provide a QAccessible::InterfaceFactory for it. The factory can be used if you link statically or do not want the added complexity of plugins. This can be an advantage if you, for instance, are delivering a 3-rd party library. All widgets and other user interface elements should have interfaces and plugins. If you want your application to support accessibility, you will need to consider the following: \list \o Qt already implements accessibility for its own widgets. We therefore recommend that you use Qt widgets where possible. \o A QAccessibleInterface needs to be implemented for each element that you want to make available to accessibility clients. \o You need to send accessibility events from the custom user interface elements that you implement. \endlist In general, it is recommended that you are somewhat familiar with MSAA, which Qt's accessibility support originally was built for. You should also study the enum values of QAccessible, which describe the roles, actions, relationships, and events that you need to consider. Note that you can examine how Qt's widgets implement their accessibility. One major problem with the MSAA standard is that interfaces are often implemented in an inconsistent way. This makes life difficult for clients and often leads to guesswork on object functionality. It is possible to implement interfaces by inheriting QAccessibleInterface and implementing its pure virtual functions. In practice, however, it is usually preferable to inherit QAccessibleObject or QAccessibleWidget, which implement part of the functionality for you. In the next section, we will see an example of implementing accessibility for a widget by inheriting the QAccessibleWidget class. \section2 The QAccessibleObject and QAccessibleWidget Convenience Classes When implementing an accessibility interface for widgets, one would as a rule inherit QAccessibleWidget, which is a convenience class for widgets. Another available convenience class, which is inherited by QAccessibleWidget, is the QAccessibleObject, which implements part of the interface for QObjects. The QAccessibleWidget provides the following functionality: \list \o It handles the navigation of the tree and hit testing of the objects. \o It handles events, roles, and actions that are common for all \l{QWidget}s. \o It handles action and methods that can be performed on all widgets. \o It calculates bounding rectangles with \l{QAccessibleInterface::}{rect()}. \o It gives \l{QAccessibleInterface::}{text()} strings that are appropriate for a generic widget. \o It sets the \l{QAccessible::State}{states} that are common for all widgets. \endlist \section2 QAccessibleWidget Example Instead of creating a custom widget and implementing an interface for it, we will show how accessibility can be implemented for one of Qt's standard widgets: QSlider. Making this widget accessible demonstrates many of the issues that need to be faced when making a custom widget accessible. The slider is a complex control that functions as a \l{QAccessible::}{Controller} for its accessible children. This relationship must be known by the interface (for \l{QAccessibleInterface::}{relationTo()} and \l{QAccessibleInterface::}{navigate()}). This can be done using a controlling signal, which is a mechanism provided by QAccessibleWidget. We do this in the constructor: \snippet doc/src/snippets/accessibilityslidersnippet.cpp 0 The choice of signal shown is not important; the same principles apply to all signals that are declared in this way. Note that we use QLatin1String to ensure that the signal name is correctly specified. When an accessible object is changed in a way that users need to know about, it notifies clients of the change by sending them an event via the accessible interface. This is how QSlider calls \l{QAccessibleInterface::}{updateAccessibility()} to indicate that its value has changed: \snippet doc/src/snippets/qabstractsliderisnippet.cpp 0 \dots \snippet doc/src/snippets/qabstractsliderisnippet.cpp 1 \dots \snippet doc/src/snippets/qabstractsliderisnippet.cpp 2 Note that the call is made after the value of the slider has changed because clients may query the new value immediately after receiving the event. The interface must be able to calculate bounding rectangles of itself and any children that do not provide an interface of their own. The \c QAccessibleSlider has three such children identified by the private enum, \c SliderElements, which has the following values: \c PageLeft (the rectangle on the left hand side of the slider handle), \c PageRight (the rectangle on the right hand side of the handle), and \c Position (the slider handle). Here is the implementation of \l{QAccessibleInterface::}{rect()}: \snippet doc/src/snippets/accessibilityslidersnippet.cpp 1 \dots \snippet doc/src/snippets/accessibilityslidersnippet.cpp 2 \dots The first part of the function, which we have omitted, uses the current \l{QStyle}{style} to calculate the slider handle's bounding rectangle; it is stored in \c srect. Notice that child 0, covered in the default case in the above code, is the slider itself, so we can simply return the QSlider bounding rectangle obtained from the superclass, which is effectively the value obtained from QAccessibleWidget::rect(). \snippet doc/src/snippets/accessibilityslidersnippet.cpp 3 Before the rectangle is returned it must be mapped to screen coordinates. The QAccessibleSlider must reimplement QAccessibleInterface::childCount() since it manages children without interfaces. The \l{QAccessibleInterface::}{text()} function returns the QAccessible::Text strings for the slider: \snippet doc/src/snippets/accessibilityslidersnippet.cpp 4 The \c slider() function returns a pointer to the interface's QSlider. Some values are left for the superclass's implementation. Not all values are appropriate for all accessible objects, as you can see for QAccessible::Value case. You should just return an empty string for those values where no relevant text can be provided. The implementation of the \l{QAccessibleInterface::}{role()} function is straightforward: \snippet doc/src/snippets/accessibilityslidersnippet.cpp 5 The role function should be reimplemented by all objects and describes the role of themselves and the children that do not provide accessible interfaces of their own. Next, the accessible interface needs to return the \l{QAccessible::State}{states} that the slider can be in. We look at parts of the \c state() implementation to show how just a few of the states are handled: \snippet doc/src/snippets/accessibilityslidersnippet.cpp 6 \dots \snippet doc/src/snippets/accessibilityslidersnippet.cpp 7 The superclass implementation of \l{QAccessibleInterface::}{state()}, uses the QAccessibleInterface::state() implementation. We simply need to disable the buttons if the slider is at its minimum or maximum. We have now exposed the information we have about the slider to the clients. For the clients to be able to alter the slider - for example, to change its value - we must provide information about the actions that can be performed and perform them upon request. We discuss this in the next section. \section2 Handling Action Requests from Clients QAccessible provides a number of \l{QAccessible::}{Action}s that can be performed on request from clients. If an accessible object supports actions, it should reimplement the following functions from QAccessibleInterface: \list \o \l{QAccessibleInterface::}{actionText()} returns strings that describe each action. The descriptions to be made available are one for each \l{QAccessible::}{Text} enum value. \o \l{QAccessibleInterface::}{doAction()} executes requests from clients to perform actions. \endlist Note that a client can request any action from an object. If the object does not support the action, it returns false from \l{QAccessibleInterface::}{doAction()}. None of the standard actions take any parameters. It is possible to provide user-defined actions that can take parameters. The interface must then also reimplement \l{QAccessibleInterface::}{userActionCount()}. Since this is not defined in the MSAA specification, it is probably only useful to use this if you know which specific AT-Clients will use the application. QAccessibleInterface gives another technique for clients to handle accessible objects. It works basically the same way, but uses the concept of methods in place of actions. The available methods are defined by the QAccessible::Method enum. The following functions need to be reimplemented from QAccessibleInterface if the accessible object is to support methods: \list \o \l{QAccessibleInterface::}{supportedMethods()} returns a QSet of \l{QAccessible::}{Method} values that are supported by the object. \o \l{QAccessibleInterface::}{invokeMethod()} executes methods requested by clients. \endlist The action mechanism will probably be substituted by providing methods in place of the standard actions. To see examples on how to implement actions and methods, you could examine the QAccessibleObject and QAccessibleWidget implementations. You might also want to take a look at the MSAA documentation. \section2 Implementing Accessible Plugins In this section we will explain the procedure of implementing accessible plugins for your interfaces. A plugin is a class stored in a shared library that can be loaded at run-time. It is convenient to distribute interfaces as plugins since they will only be loaded when required. Creating an accessible plugin is achieved by inheriting QAccessiblePlugin, reimplementing \l{QAccessiblePlugin::}{keys()} and \l{QAccessiblePlugin::}{create()} from that class, and adding one or two macros. The \c .pro file must be altered to use the plugin template, and the library containing the plugin must be placed on a path where Qt searches for accessible plugins. We will go through the implementation of \c SliderPlugin, which is an accessible plugin that produces interfaces for the QAccessibleSlider we implemented in the \l{QAccessibleWidget Example}. We start with the \c key() function: \snippet doc/src/snippets/accessibilitypluginsnippet.cpp 0 We simply need to return the class name of the single interface our plugin can create an accessible interface for. A plugin can support any number of classes; just add more class names to the string list. We move on to the \c create() function: \snippet doc/src/snippets/accessibilitypluginsnippet.cpp 1 We check whether the interface requested is for the QSlider; if it is, we create and return an interface for it. Note that \c object will always be an instance of \c classname. You must return 0 if you do not support the class. \l{QAccessible::}{updateAccessibility()} checks with the available accessibility plugins until it finds one that does not return 0. Finally, you need to include macros in the cpp file: \snippet doc/src/snippets/accessibilitypluginsnippet.cpp 2 The Q_EXPORT_PLUGIN2 macro exports the plugin in the \c SliderPlugin class into the \c acc_sliderplugin library. The first argument is the name of the plugin library file, excluding the file suffix, and the second is the class name. For more information on plugins, consult the plugins \l{How to Create Qt Plugins}{overview document}. You can omit the first macro unless you want the plugin to be statically linked with the application. \section2 Implementing Interface Factories If you do not want to provide plugins for your accessibility interfaces, you can use an interface factory (QAccessible::InterfaceFactory), which is the recommended way to provide accessible interfaces in a statically-linked application. A factory is a function pointer for a function that takes the same parameters as \l{QAccessiblePlugin}'s \l{QAccessiblePlugin::}{create()} - a QString and a QObject. It also works the same way. You install the factory with the \l{QAccessible::}{installFactory()} function. We give an example of how to create a factory for the \c SliderPlugin class: \snippet doc/src/snippets/accessibilityfactorysnippet.cpp 0 \dots \snippet doc/src/snippets/accessibilityfactorysnippet.cpp 1 \omit \section1 Implementing Bridges for Other Assistive Technologies An accessibility bridge provides the means for an assistive technology to talk to Qt. On Windows and Mac, the built-in bridges will be used. On UNIX, however, there are no built-in standard assistive technology, and it might therefore be necessary to implement an accessible bridge. A bridge is implemented by inheriting QAccessibleBridge for the technology to support. The class defines the interface that Qt needs an assistive technology to support: \list \o A root object. This is the root in the accessible object tree and is of type QAccessibleInterface. \o Receive events from from accessible objects. \endlist The root object is set with the \l{QAccessibleBridge::}{setRootObject()}. In the case of Qt, this will always be an interface for the QApplication instance of the application. Event notification is sent through \l{QAccessibleBridge::}{notifyAccessibilityUpdate()}. This function is called by \l{QAccessible::}{updateAccessibility()}. Even though the bridge needs only to implement these two functions, it must be able to communicate the entire QAccessibleInterface to the underlying technology. How this is achieved is, naturally, up to the individual bridge and none of Qt's concern. As with accessible interfaces, you distribute accessible bridges in plugins. Accessible bridge plugins are subclasses of the QAccessibleBridgePlugin class; the class defines the functions \l{QAccessibleBridgePlugin::}{create()} and \l{QAccessibleBridgePlugin::}{keys()}, which must me reimplemented. If Qt finds a built-in bridge to use, it will ignore any available plugins. \endomit \section1 Further Reading The \l{Cross-Platform Accessibility Support in Qt 4} document contains a more general overview of Qt's accessibility features and discusses how it is used on each platform. issues */