a11y: Add new QAccessibleAnnouncementEvent

Add a new QAccessibleAnnouncementEvent that
can be used to request the announcement of
a message by assistive technologies
(most prominently screen readers).

The priority/urgency of the message can
be specified using one of the values of the
newly added AnnouncementPriority enum.

As suggested by the maintainer of the Orca screen reader
in a similar merge request for GTK [1], add some
clarification that assertive priority should only be
used for things that are actually worth interrupting
the user's current task immediately rather than waiting
for the next graceful opportunity like the end of the
sentence currently spoken by the screen reader.

All of AT-SPI on Linux, UIA on Windows and NSAccessibility
on macOS have corresponding API:

* Linux/AT-SPI: Announcement event (initially added in
  commit [2], possibility to set priority/politeness level
  added in commit [3])

* Windows/UIA: UiaRaiseNotificationEvent [4]

* macOS/NSAccessibility: announcementRequested
  function [5]

Bridging to the corresponding platform API in the
platform backends is left for separate upcoming
commits.

[1] https://gitlab.gnome.org/GNOME/gtk/-/merge_requests/6461#note_1993454
[2] 26835da299
[3] 32c9420ec8
[4] https://learn.microsoft.com/en-us/windows/win32/api/uiautomationcoreapi/nf-uiautomationcoreapi-uiaraisenotificationevent
[5] https://developer.apple.com/documentation/appkit/nsaccessibility/notification/1530633-announcementrequested

[ChangeLog][QtGui][QAccessibleAnnouncementEvent] Added new
QAccessibleAnnouncementEvent that can be used to request
the announcement of a message by assistive technologies.

Task-number: QTBUG-75003
Change-Id: Ief60ae7c5a9c8bf8404ad9b2749e253acc5d77c5
Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
bb10
Michael Weghorn 2024-04-09 16:43:21 +02:00
parent 1f667ba70e
commit 010952a55e
3 changed files with 112 additions and 0 deletions

View File

@ -173,6 +173,7 @@ Q_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core");
\value ActionChanged An action has been changed.
\value ActiveDescendantChanged
\value Alert A system alert (e.g., a message from a QMessageBox)
\value [since 6.8] Announcement The announcement of a message is requested.
\value AttributeChanged
\value ContextHelpEnd Context help (QWhatsThis) for an object is finished.
\value ContextHelpStart Context help (QWhatsThis) for an object is initiated.
@ -449,6 +450,30 @@ Q_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core");
\sa QAccessibleAttributesInterface
*/
/*! \enum QAccessible::AnnouncementPriority
This enum describes the priority for announcements used by the
\l QAccessibleAnnouncementEvent.
\since 6.8
With \a QAccessible::AnouncementPriority::Polite, assistive technologies
should announce the message at the next graceful opportunity such as at the
end of speaking the current sentence or when the user pauses typing.
When specifying \a QAccessible::AnouncementPriority::Assertive, assistive
technologies should notify the user immediately.
Because an interruption might disorient users or cause them to not complete
their current task, \a QAccessible::AnouncementPriority::Assertive should
not be used unless the interruption is imperative.
\value Polite The announcement has normal priority.
\value Assertive The announcement has high priority and should notify
the user immediately, even if that means interrupting the user's
current task.
\sa QAccessibleAnnouncementEvent
*/
/*!
\enum QAccessible::InterfaceType
@ -1778,7 +1803,56 @@ QAccessibleTextSelectionEvent::~QAccessibleTextSelectionEvent()
{
}
/*!
\since 6.8
\class QAccessibleAnnouncementEvent
\ingroup accessibility
\inmodule QtGui
\brief The QAccessibleAnnouncementEvent is used to request the announcement
of a given message by assistive technologies.
This class is used with \l QAccessible::updateAccessibility().
*/
/*! \fn QAccessibleAnnouncementEvent::QAccessibleAnnouncementEvent(QObject *object, const QString &message)
Constructs a new QAccessibleAnnouncementEvent event for \a object
to request the announcement of \a message with priority \l QAccessible::AnnouncementPriority::Polite.
\l QAccessibleAnnouncementEvent::setPriority can be used to adjust the priority.
*/
/*! \fn QAccessibleAnnouncementEvent::QAccessibleAnnouncementEvent(QAccessibleInterface *iface, const QString &message)
Constructs a new QAccessibleAnnouncementEvent event for \a iface
to request the announcement of \a message with priority \l QAccessible::AnnouncementPriority::Polite.
\l QAccessibleAnnouncementEvent::setPriority can be used to adjust the priority.
*/
/*! \fn QString QAccessibleAnnouncementEvent::message() const
Returns the message.
*/
/*! \fn QAccessible::AnnouncementPriority QAccessibleAnnouncementEvent::priority() const
Returns the priority.
*/
/*! \fn void QAccessibleAnnouncementEvent::setPriority(QAccessible::AnnouncementPriority priority)
Sets the priority with which the announcement will be requested to \a priority.
*/
/*!
\internal
*/
QAccessibleAnnouncementEvent::~QAccessibleAnnouncementEvent()
{
}
/*!
Returns the QAccessibleInterface associated with the event.

View File

@ -316,6 +316,7 @@ public:
Q_ASSERT(m_type != QAccessible::TextRemoved);
Q_ASSERT(m_type != QAccessible::TextUpdated);
Q_ASSERT(m_type != QAccessible::TableModelChanged);
Q_ASSERT(m_type != QAccessible::Announcement);
}
inline QAccessibleEvent(QAccessibleInterface *iface, QAccessible::Event typ)
@ -330,6 +331,7 @@ public:
Q_ASSERT(m_type != QAccessible::TextRemoved);
Q_ASSERT(m_type != QAccessible::TextUpdated);
Q_ASSERT(m_type != QAccessible::TableModelChanged);
Q_ASSERT(m_type != QAccessible::Announcement);
m_uniqueId = QAccessible::uniqueId(iface);
m_object = iface->object();
}
@ -605,6 +607,36 @@ protected:
int m_lastColumn;
};
class Q_GUI_EXPORT QAccessibleAnnouncementEvent : public QAccessibleEvent
{
public:
inline QAccessibleAnnouncementEvent(QObject *object, const QString &message)
: QAccessibleEvent(object, QAccessible::InvalidEvent)
, m_message(message)
, m_priority(QAccessible::AnnouncementPriority::Polite)
{
m_type = QAccessible::Announcement;
}
inline QAccessibleAnnouncementEvent(QAccessibleInterface *iface, const QString &message)
: QAccessibleEvent(iface, QAccessible::InvalidEvent)
, m_message(message)
, m_priority(QAccessible::AnnouncementPriority::Polite)
{
m_type = QAccessible::Announcement;
}
~QAccessibleAnnouncementEvent();
QString message() const { return m_message; }
QAccessible::AnnouncementPriority priority() const { return m_priority; }
void setPriority(QAccessible::AnnouncementPriority priority) { m_priority = priority; };
protected:
QString m_message;
QAccessible::AnnouncementPriority m_priority;
};
#ifndef Q_QDOC
#define QAccessibleInterface_iid "org.qt-project.Qt.QAccessibleInterface"
Q_DECLARE_INTERFACE(QAccessibleInterface, QAccessibleInterface_iid)

View File

@ -101,6 +101,7 @@ public:
HelpChanged = 0x80A0,
DefaultActionChanged = 0x80B0,
AcceleratorChanged = 0x80C0,
Announcement = 0x80D0,
InvalidEvent
};
@ -367,6 +368,11 @@ public:
Level,
};
enum class AnnouncementPriority {
Polite,
Assertive
};
typedef QAccessibleInterface*(*InterfaceFactory)(const QString &key, QObject*);
typedef void(*UpdateHandler)(QAccessibleEvent *event);
typedef void(*RootObjectHandler)(QObject*);