blob: e163755bc3c1571f47a714c1775ac20f8f333a36 [file] [log] [blame]
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the documentation of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:FDL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and The Qt Company. For licensing terms
** and conditions see https://www.qt.io/terms-conditions. For further
** information use the contact form at https://www.qt.io/contact-us.
**
** GNU Free Documentation License Usage
** Alternatively, this file may be used under the terms of the GNU Free
** Documentation License version 1.3 as published by the Free Software
** Foundation and appearing in the file included in the packaging of
** this file. Please review the following information to ensure
** the GNU Free Documentation License version 1.3 requirements
** will be met: https://www.gnu.org/licenses/fdl-1.3.html.
** $QT_END_LICENSE$
**
****************************************************************************/
/*!
\group accessibility
\brief Functions ensuring communication between accessible applications and accessibility tools.
\title Accessibility Classes
*/
/*!
\page accessible.html
\title Accessibility
\brief How to make your applications accessible to those with disabilities.
\nextpage Accessibility for QWidget Applications
\ingroup best-practices
\tableofcontents
\section1 Introduction
Accessibility in computer software is making applications usable
for people with different abilities.
It is important to take different people's needs into account, for example,
in case of low vision, hearing, dexterity, or cognitive problems.
Some examples of accessibility measures are
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.
A basic checklist that any application should aim for:
\list
\li \b {Usability} - Usability and user centric design generally lead to
more usable applications, including improvements for people with various abilities.
\li \b {Fonts} - Font settings should follow the system/platform. This allows users to select
fonts for readability and increasing the font size.
\li \b {Colors} - Provide enough contrast and consider the most common cases of low
vision and color blindness. Make sure that the application is usable, for example,
for people with red/green blindness, and don't depend on colors only.
\li \b {Scalable UI} - A user interface that works in various sizes and properly supports
different fonts and accommodates size changes.
\li \b {Sounds} - Do not exclusively rely on sound notifications, provide a visual alternative
when a sound signal is imperative to using the application.
\li \b {Spelling} - Offer spell checking wherever it makes sense, even when only a single word is expected.
\li \b {Assistive Technology} - Support the use of assistive tools (AT). Either use standard widgets/controls
which support ATs out of the box, or make sure that your custom widgets and controls support
accessibility properly. In order to learn more about this read on below.
\endlist
This part of the documentation assumes that the basics for accessibility,
which go hand in hand with usability, are already in good shape.
The rest of this document focuses more specifically on supporting assistive technology.
Assistive Tools (or ATs) come in great variety and help users with different tasks.
For this reason what individual applications offer (with the help of Qt) is a generic
API that allows to inspect what is on screen in a semantic way and offers the typical
interactions with the UI elements.
Applications do not usually communicate directly with the
assistive tools, but through a platform specific API.
Generally the communication with the ATs works though an IPC mechanism.
Semantic information about user interface elements, such as
buttons and scroll bars, is exposed to the assistive technologies.
Qt supports UI Automation on Windows,
\macos Accessibility on \macos, and AT-SPI via DBus on Unix/X11.
The platform specific technologies are abstracted by Qt,
so that applications do not need any platform specific changes to work with the different
native APIs. Qt tries to make adding accessibility support to your application as easy
as possible, only a few changes from your side may be required to allow even more users to enjoy it.
The main reason to consult this documentation is to learn how to make custom \l QWidget subclasses
and \l {QQuickItem}s accessible.
In this overview document, we will examine the overall Qt
accessibility architecture, and how to implement accessibility for
custom widgets and elements.
\section1 Making Applications Accessible
These two pages focus on giving an overview of how to achieve
good accessibility:
\l{Accessibility for QWidget Applications}
\l{Accessibility for Qt Quick Applications}
These classes provide support for accessible applications:
\annotatedlist accessibility
*/
/*!
\page accessible-qwidget.html
\title Accessibility for QWidget Applications
\brief How to make your applications accessible to those with disabilities.
\previouspage Accessibility
\nextpage Accessibility for Qt Quick Applications
\tableofcontents
\section1 Introduction
We will focus on the Qt accessibility interface \l {QAccessibleInterface}
and how to make applications accessible.
\section2 Accessibility in QWidget based applications
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. We will examine the enums
in the course of this document.
The structure of the UI is represented as a tree of
QAccessibleInterface subclasses. This is often a mirror of the
hierarchy of QWidgets that make up the UI of the application.
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
\l QAccessible::queryAccessibleInterface().
The members and enums in QAccessible are used to describe
accessible objects:
\list
\li \l{QAccessible::}{Role}: Describes the role the object
fills in the user interface, e.g., if it is a
window, a text edit, or a cell in a table.
\li \l{QAccessible::}{Relation}: Describes the relationship
between objects in the object hierarchy.
\li \l{QAccessible::}{State}: The objects can be in a number
of different states. Examples of states are whether
the object is disabled, if it has focus,
or if it provides a pop-up menu.
\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.
\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
navigate the tree with the QAccessibleInterface::parent(), QAccessibleInterface::childCount()
and QAccessibleInterface::child() functions.
Qt provides accessible interfaces for its widgets and for Qt Quick Controls.
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
QAccessibleInterface::relations().
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
\li Source Object
\li Target Object
\li Relation
\row
\li Slider
\li Indicator
\li Controller
\row
\li Indicator
\li Slider
\li Controlled
\row
\li Slider
\li Application
\li Ancestor
\row
\li Application
\li Slider
\li Child
\row
\li PushButton
\li Indicator
\li 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.
\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
\li Qt already implements accessibility for its own widgets.
We therefore recommend that you use Qt widgets where possible.
\li A QAccessibleInterface needs to be implemented for each element
that you want to make available to accessibility clients.
\li 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
\li It handles the navigation of the tree and
hit testing of the objects.
\li It handles events, roles, and actions that are common for all
\l{QWidget}s.
\li It handles action and methods that can be performed on
all widgets.
\li It calculates bounding rectangles with
\l{QAccessibleInterface::}{rect()}.
\li It gives \l{QAccessibleInterface::}{text()} strings that are
appropriate for a generic widget.
\li 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 is implemented for one of
Qt's standard widgets: QSlider. The accessible interface,
QAccessibleSlider, inherits from QAccessibleAbstractSlider, which
in turn inherits QAccessibleWidget. You do not need to examine the
QAccessibleAbstractSlider class to read this section. If you want
to take a look, the code for all of Qt's accessible interfaces are
found in qtbase/src/widgets/accessible. Here is the
QAccessibleSlider's constructor:
\snippet snippets/accessibilityslidersnippet.cpp 0
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::}{parent()}, \l{QAccessibleInterface::}{child()} and
\l{QAccessibleInterface::}{relations()}). This can be done
using a controlling signal, which is a mechanism provided by
QAccessibleWidget. We do this in the constructor:
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{QAccessible::}{updateAccessibility()} to indicate that
its value has changed:
\snippet snippets/qabstractsliderisnippet.cpp 0
\dots
\snippet snippets/qabstractsliderisnippet.cpp 1
\dots
\snippet 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 snippets/accessibilityslidersnippet.cpp 1
\dots
\snippet 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 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 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 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 snippets/accessibilityslidersnippet.cpp 6
\dots
\snippet 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
Applications can expose actions, which can be invoked by the
client.
In order to support actions in an object, inherit the
\l {QAccessibleActionInterface}.
Interactive elements should expose functionality triggered
by mouse interaction, for example.
A button should, for example, implement a click action.
Setting the focus is another action that should be implemented
for widgets that accept receive the focus.
You need to re-implement \l{QAccessibleActionInterface::}{actionNames()}
to return a list of all actions that the object supports.
This list should not be localized.
There are two functions that give information about the actions
that must return localized strings:
\l{QAccessibleActionInterface::}{localizedActionName()} and
\l{QAccessibleActionInterface::}{localizedActionDescription()}.
These functions can be used by the client to present the actions to the user.
In general, the name should be concise and only consist of a single word, such as "press".
There is a list of standard action names and localizations available
that should be used when the action fits. This makes it easier for
clients to understand the semantics, and Qt will try to expose them
correctly on the different platforms.
Of course the action also needs a way to be triggered.
\l{QAccessibleActionInterface::}{doAction()} should
invoke the action as advertised by name and description.
To see examples on how to implement actions and methods, you
could examine the implementations for Qt's standard widgets such as
QAccessiblePushButton.
\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,
defining the supported class names in the plugin's JSON description and
reimplementing \l{QAccessiblePlugin::}{create()} from QAccessiblePlugin.
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 the QAccessibleSlider interface
from the \l{QAccessibleWidget Example}. We start with the \c key()
function:
\snippet 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 snippets/accessibilitypluginsnippet.cpp 1
We check whether the interface requested is for 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 snippets/accessibilitypluginsnippet.cpp 2
The Q_PLUGIN_METADATA macro exports the plugin in the \c
SliderPlugin class into the \c acc_sliderplugin library. The first
argument is the plugins IID and the second is an optional json file
which holds metadata information for the plugin. For more
information on plugins, you can consult the plugins \l{How to
Create Qt Plugins}{overview document}.
It does not matter if you need the plugin to be statically or
dynamically 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 QAccessibleSlider interface:
\snippet snippets/accessibilityfactorysnippet.cpp 0
\dots
\snippet 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
\li A root object. This is the root in the accessible
object tree and is of type QAccessibleInterface.
\li 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
*/
/*!
\page accessible-qtquick.html
\title Accessibility for Qt Quick Applications
\brief How to make your applications accessible to those with disabilities.
\startpage Accessibility
\previouspage Accessibility for QWidget Applications
\ingroup best-practices
\tableofcontents
\section1 Introduction
We will explain how to make Qt Quick applications accessible.
This can be compared to making web application accessible.
You simply need to assign a few properties when creating controls such
as buttons in QML.
The most important property for this purpose is the attached property
\l {Accessible}.
*/