summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Weghorn <m.weghorn@posteo.de>2024-04-09 16:17:58 +0200
committerMichael Weghorn <m.weghorn@posteo.de>2024-05-14 00:32:37 +0200
commit24986ccb7b2020cbb574700a31667e88ed243194 (patch)
treecc72cf5f76a432cc669914f827cdd935ff548fe0
parentc9e62c24440e99ace02dcceffea2ae6542f49224 (diff)
a11y atspi: Forward new QAccessibleAnnouncementEvent to AT-SPI
Forward the newly added QAccessibleAnnouncementEvent to the AT-SPI level as a corresponding AT-SPI Announcement event. The AtspiLive enum to specify the priority/politeness level was added in at-spi2-core/libatspi commit [1] which is contained in libatspi versions >= 2.50, so define the relevant values ATSPI_LIVE_ASSERTIVE and ATSPI_LIVE_POLITE manually for older libatspi versions. (Note that the mention of binary compatibility in above-mentioned at-spi2-core commit only applies for ATK, not AT-SPI, so is not relevant here.) This makes announcement from the example app attached to QTBUG-75003 work when using the Orca screen reader on Linux. [1] https://gitlab.gnome.org/GNOME/at-spi2-core/-/commit/32c9420ec82f07da8033c675a2bbf25e535f0509 Task-number: QTBUG-75003 Change-Id: I752aadca2abdda58b3869e17e74fcd9d7572f915 Reviewed-by: Axel Spoerl <axel.spoerl@qt.io> Reviewed-by: Volker Hilsheimer <volker.hilsheimer@qt.io>
-rw-r--r--src/gui/accessible/linux/atspiadaptor.cpp38
-rw-r--r--src/gui/accessible/linux/atspiadaptor_p.h3
2 files changed, 41 insertions, 0 deletions
diff --git a/src/gui/accessible/linux/atspiadaptor.cpp b/src/gui/accessible/linux/atspiadaptor.cpp
index b3269a2a95..2cebad1453 100644
--- a/src/gui/accessible/linux/atspiadaptor.cpp
+++ b/src/gui/accessible/linux/atspiadaptor.cpp
@@ -35,6 +35,13 @@
#define ATSPI_COORD_TYPE_PARENT 2
#endif
+// ATSPI_*_VERSION defines were added in libatspi 2.50,
+// as was the AtspiLive enum; define values here for older versions
+#if !defined(ATSPI_MAJOR_VERSION) || !defined(ATSPI_MINOR_VERSION) || ATSPI_MAJOR_VERSION < 2 || ATSPI_MINOR_VERSION < 50
+#define ATSPI_LIVE_POLITE 1
+#define ATSPI_LIVE_ASSERTIVE 2
+#endif
+
QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
@@ -47,6 +54,7 @@ AtSpiAdaptor::AtSpiAdaptor(DBusConnection *connection, QObject *parent)
, sendFocus(0)
, sendObject(0)
, sendObject_active_descendant_changed(0)
+ , sendObject_announcement(0)
, sendObject_attributes_changed(0)
, sendObject_bounds_changed(0)
, sendObject_children_changed(0)
@@ -678,6 +686,8 @@ void AtSpiAdaptor::setBitFlag(const QString &flag)
if (false) {
} else if (right.startsWith("ActiveDescendantChanged"_L1)) {
sendObject_active_descendant_changed = 1;
+ } else if (right.startsWith("Announcement"_L1)) {
+ sendObject_announcement = 1;
} else if (right.startsWith("AttributesChanged"_L1)) {
sendObject_attributes_changed = 1;
} else if (right.startsWith("BoundsChanged"_L1)) {
@@ -929,6 +939,26 @@ void AtSpiAdaptor::notifyStateChange(QAccessibleInterface *interface, const QStr
sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1, "StateChanged"_L1, stateArgs);
}
+void AtSpiAdaptor::sendAnnouncement(QAccessibleAnnouncementEvent *event)
+{
+ QAccessibleInterface *iface = event->accessibleInterface();
+ if (!iface) {
+ qCWarning(lcAccessibilityAtspi, "Announcement event has no accessible set.");
+ return;
+ }
+ if (!iface->isValid()) {
+ qCWarning(lcAccessibilityAtspi) << "Announcement event with invalid accessible: " << iface;
+ return;
+ }
+
+ const QString path = pathForInterface(iface);
+ const QString message = event->message();
+ const QAccessible::AnnouncementPriority prio = event->priority();
+ const int politeness = (prio == QAccessible::AnnouncementPriority::Assertive) ? ATSPI_LIVE_ASSERTIVE : ATSPI_LIVE_POLITE;
+
+ const QVariantList args = packDBusSignalArguments(QString(), politeness, 0, QVariant::fromValue(QDBusVariant(message)));
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1, "Announcement"_L1, args);
+}
/*!
This function gets called when Qt notifies about accessibility updates.
@@ -1003,6 +1033,14 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
sendFocusChanged(event->accessibleInterface());
break;
}
+
+ case QAccessible::Announcement: {
+ if (sendObject || sendObject_announcement) {
+ QAccessibleAnnouncementEvent *announcementEvent = static_cast<QAccessibleAnnouncementEvent*>(event);
+ sendAnnouncement(announcementEvent);
+ }
+ break;
+ }
case QAccessible::TextInserted:
case QAccessible::TextRemoved:
case QAccessible::TextUpdated: {
diff --git a/src/gui/accessible/linux/atspiadaptor_p.h b/src/gui/accessible/linux/atspiadaptor_p.h
index c2f9b60ebf..aab15d4501 100644
--- a/src/gui/accessible/linux/atspiadaptor_p.h
+++ b/src/gui/accessible/linux/atspiadaptor_p.h
@@ -85,6 +85,8 @@ private:
void notifyStateChange(QAccessibleInterface *interface, const QString& state, int value);
+ void sendAnnouncement(QAccessibleAnnouncementEvent *event);
+
// accessible helper functions
AtspiRole getRole(QAccessibleInterface *interface) const;
QSpiRelationArray relationSet(QAccessibleInterface *interface, const QDBusConnection &connection) const;
@@ -130,6 +132,7 @@ private:
// all of object
uint sendObject : 1;
uint sendObject_active_descendant_changed : 1;
+ uint sendObject_announcement : 1;
uint sendObject_attributes_changed : 1;
uint sendObject_bounds_changed : 1;
uint sendObject_children_changed : 1;