diff options
author | Michael Weghorn <m.weghorn@posteo.de> | 2023-11-10 18:25:02 +0100 |
---|---|---|
committer | Volker Hilsheimer <volker.hilsheimer@qt.io> | 2024-02-29 04:44:22 +0000 |
commit | fb5ffe862688a87cfc136113e067bcba0c49a7ae (patch) | |
tree | 1612b26c714875043714d4709a1142bb3b946655 /src/gui | |
parent | 6164b17d226a4dd2099a852a6c34bae6fa19876d (diff) |
a11y: Add new QAccessibleAttributesInterface
This adds a new QAccessibleAttributes interface
that implements support for reporting (object)
attributes (as compared to offset-specific text
attributes, which are handled by the
QAccessibleTextInterface).
The concept of object attributes/properties can
be found in all of ARIA, AT-SPI2 on Linux,
IAccessible2 and UIA on Windows and NSAccessibility
on macOS, and while some of the properties/attributes
on these platforms can be mapped to from information
retrieved via existing QAccessible* interfaces, a lot
of relevant information cannot be made available this
way.
The new interface is meant to bridge this gap.
Each attribute is handled as a key-value pair.
Other than for the handling of text attributes
(where a single string is used for all attributes,
s. QAccessibleTextInterface::attributes), the
object attributes handled by the new interface
use the newly introduced QAccessible::Attribute enum class
for keys. This helps to clearly define the semantics
of each attribute and simplifies mapping to the different
platform representations in the platform a11y bridges.
Initially, two attribute types, Custom
and Level are added, s. the documentation added
with this commit for more details.
Mapping of these two attributes to their platform
equivalent for AT-SPI2 on Linux and UIA on Windows
will be added in following commits.
The Core Accessibility API Mappings specification [1]
can be very useful when considering new attributes
to add and how to bridge them to the specific
platform APIs.
Conceptually, the possibility to expose object-specific
attributes might seem a good fit for the existing
QAccessibleInterface, but adding new virtual methods
to non-leaf classes would be an ABI-incompatible
change [2], so adding a new interface/class is
necessary.
There is also a related discussion for Gtk 4 in [3],
which - other than Gtk 3 - currently also lacks
API to support many AT-SPI object attributes relevant
for assistive technology like screen readers.
The implementation here is also inspired by the
dicussion there.
A sample implementation for LibreOffice can be
found at [4].
[1] https://www.w3.org/TR/core-aam-1.2/
[2] https://community.kde.org/Policies/Binary_Compatibility_Examples#Add_new_virtuals_to_a_non-leaf_class
[3] https://gitlab.gnome.org/GNOME/gtk/-/issues/6196
[4] https://gerrit.libreoffice.org/c/core/+/159309
[ChangeLog][QtGui][QAccessibleAttributesInterface] Added new
QAccessibleAttributesInterface that can be used to expose
object attributes/properties to assistive technology.
Task-number: QTBUG-119057
Change-Id: I9d51c818e82673d1e755a3c909d3e8f5bb064a35
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
Diffstat (limited to 'src/gui')
-rw-r--r-- | src/gui/accessible/qaccessible.cpp | 88 | ||||
-rw-r--r-- | src/gui/accessible/qaccessible.h | 13 | ||||
-rw-r--r-- | src/gui/accessible/qaccessible_base.h | 8 |
3 files changed, 107 insertions, 2 deletions
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp index ea8ab097d1..46bca16dad 100644 --- a/src/gui/accessible/qaccessible.cpp +++ b/src/gui/accessible/qaccessible.cpp @@ -412,6 +412,43 @@ Q_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core"); \sa QAccessibleTextInterface */ +/*! \enum QAccessible::Attribute + This enum describes different types of attributes used by the + \l QAccessibleAttributesInterface. + \since 6.8 + + These attributes are comparable to the concept of properties/(object) + attributes found in ARIA, AT-SPI2, IAccessible, UIA and NSAccessibility + and are mapped to their platform counterpart where applicable. + + Each attribute is handled as a key-value pair, with the values of this + enumeration being used as keys. + + Attribute values are represented in a \l QVariant. The type of the value + stored in the \l QVariant is fixed and specified below for each of the + attribute types. + + \value Custom value type: \a QHash<QString, QString> + The \a Custom attribute is special in that + it can effectively represent multiple attributes at + once, since it itself is a \l QHash used to represent + key-value pairs. + For platforms supporting custom key-value pairs for + attributes, those set in the \a Custom attribute + are bridged to the platform layer without applying any + translation to platform-specific attributes. In general, + the other, more strongly typed attributes should be used. + This attribute can e.g. be used for prototyping + before officially adding an official new enumeration value + for a specific feature. + \value Level value type: \a int + Defines the hierarchical level of an element within a structure, + e.g. the heading level of a heading. This attribute conceptually + matches the "aria-level" property in ARIA. + + \sa QAccessibleAttributesInterface +*/ + /*! \enum QAccessible::InterfaceType @@ -431,8 +468,9 @@ Q_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core"); \value TableCellInterface For cells in a TableInterface object. \value HyperlinkInterface For hyperlink nodes (usually embedded as children of text nodes) \value [since 6.5] SelectionInterface For non-text objects that support selection of child objects. + \value [since 6.8] AttributesInterface For objects that support object-specific attributes. - \sa QAccessibleInterface::interface_cast(), QAccessibleTextInterface, QAccessibleValueInterface, QAccessibleActionInterface, QAccessibleTableInterface, QAccessibleTableCellInterface, QAccessibleSelectionInterface + \sa QAccessibleInterface::interface_cast(), QAccessibleTextInterface, QAccessibleValueInterface, QAccessibleActionInterface, QAccessibleTableInterface, QAccessibleTableCellInterface, QAccessibleSelectionInterface, QAccessibleAttributesInterface */ #if QT_CONFIG(accessibility) @@ -3069,6 +3107,54 @@ bool QAccessibleSelectionInterface::isSelected(QAccessibleInterface *childItem) */ +/*! + \since 6.8 + \class QAccessibleAttributesInterface + \inmodule QtGui + \ingroup accessibility + + \brief The QAccessibleAttributesInterface class implements support for + reporting attributes for an accessible object. + + Attributes are key-value pairs. Values are stored in \l QVariant. + + The \a QAccessible::Attributes enumeration describes the available keys and + documents which type to use for the value of each key. + + While the text-specific attributes handled by \l QAccessibleTextInterface::attributes + are specific to objects implementing text and are specific to a specific text + position/offset, the attributes handled by the \l QAccessibleAttributesInterface + can be used for objects of any role and apply for the whole object. + + Classes already implementing \l QAccessibleTextInterface for text-specific attrtibutes + may want to implement \l QAccessibleAttributesInterface in addition for object-specific + attributes. +*/ + +/*! + + Destroys the QAccessibleAttributesInterface. +*/ +QAccessibleAttributesInterface::~QAccessibleAttributesInterface() +{ +} + +/*! + \fn QList<QAccessible::Attribute> QAccessibleAttributesInterface::attributeKeys() const + + Returns the keys of all attributes the object supports. The \l QAccessible::Attribute + enumeration describes available keys. +*/ + +/*! + \fn QVariant QAccessibleAttributesInterface::attributeValue(QAccessible::Attribute key) const + + Returns the value of the attribute \a key of this object. + + If the specificed attribute is not set for this object, an invalid + \l QVariant is returned. +*/ + /*! \internal */ QString qAccessibleLocalizedActionDescription(const QString &actionName) { diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h index 3fdc4eb7d9..0a92e76c73 100644 --- a/src/gui/accessible/qaccessible.h +++ b/src/gui/accessible/qaccessible.h @@ -43,6 +43,7 @@ class QAccessibleTableInterface; class QAccessibleTableCellInterface; class QAccessibleHyperlinkInterface; class QAccessibleSelectionInterface; +class QAccessibleAttributesInterface; class QAccessibleTableModelChangeEvent; class Q_GUI_EXPORT QAccessibleInterface @@ -106,6 +107,9 @@ public: inline QAccessibleSelectionInterface *selectionInterface() { return reinterpret_cast<QAccessibleSelectionInterface *>(interface_cast(QAccessible::SelectionInterface)); } + inline QAccessibleAttributesInterface *attributesInterface() + { return reinterpret_cast<QAccessibleAttributesInterface *>(interface_cast(QAccessible::AttributesInterface)); } + virtual void virtual_hook(int id, void *data); virtual void *interface_cast(QAccessible::InterfaceType) @@ -284,6 +288,15 @@ public: virtual bool clear() = 0; }; +class Q_GUI_EXPORT QAccessibleAttributesInterface +{ +public: + virtual ~QAccessibleAttributesInterface(); + virtual QList<QAccessible::Attribute> attributeKeys() const = 0; + virtual QVariant attributeValue(QAccessible::Attribute key) const = 0; +}; + + class Q_GUI_EXPORT QAccessibleEvent { Q_DISABLE_COPY(QAccessibleEvent) diff --git a/src/gui/accessible/qaccessible_base.h b/src/gui/accessible/qaccessible_base.h index 74926a3565..2d2b1de316 100644 --- a/src/gui/accessible/qaccessible_base.h +++ b/src/gui/accessible/qaccessible_base.h @@ -349,7 +349,8 @@ public: TableInterface, TableCellInterface, HyperlinkInterface, - SelectionInterface + SelectionInterface, + AttributesInterface, }; enum TextBoundaryType { @@ -361,6 +362,11 @@ public: NoBoundary }; + enum class Attribute { + Custom, + Level, + }; + typedef QAccessibleInterface*(*InterfaceFactory)(const QString &key, QObject*); typedef void(*UpdateHandler)(QAccessibleEvent *event); typedef void(*RootObjectHandler)(QObject*); |