From 063344c8b99d046be92fcbc2c631a79c59ad8a6e Mon Sep 17 00:00:00 2001 From: Michael Weghorn Date: Fri, 26 Aug 2022 15:52:40 +0200 Subject: [PATCH] a11y atspi: Send SelectionChanged AT-SPI event on selection change MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When using QAccessibleEvents of types QAccessible::Selection, QAccessible::SelectionAdd and QAccessible::SelectionRemove, Qt (internally) also always uses QAccessbibleEvent::setChild to set the child that has been (un)selected. As a consequence, the interface retrieved using QAccessibleEvent::accessibleInterface here is not the a11y object in which the selection has changed, but the child, so notifying about a change to its selected state (as happens here in the AT-SPI adapter) is in line with that. For AT-SPI, assistive technology (like the Orca screen reader) often reacts to the SelectionChanged event on the object managing the selection, so send a corresponding event for the parent of the (un)selected child as well. (Besides the lack of support for the AT-SPI Selection interface - s. QTBUG-105909 - the fact that this event wasn't sent previously e.g. turned out to be one reason for the Orca screen reader not announcing selected cells in the Qt 6 based UI variant of LibreOffice Calc.) Change-Id: Icc8b9a7ecc77bc5394fd1ab4f8163caed951ba86 Reviewed-by: Tor Arne Vestbø --- src/gui/accessible/linux/atspiadaptor.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/gui/accessible/linux/atspiadaptor.cpp b/src/gui/accessible/linux/atspiadaptor.cpp index d8157641c9c..91d0e47415c 100644 --- a/src/gui/accessible/linux/atspiadaptor.cpp +++ b/src/gui/accessible/linux/atspiadaptor.cpp @@ -1061,10 +1061,23 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event) qCWarning(lcAccessibilityAtspi) << "Selection event from invalid accessible."; return; } + // send event for change of selected state for the interface itself QString path = pathForInterface(iface); int selected = iface->state().selected ? 1 : 0; QVariantList stateArgs = packDBusSignalArguments("selected"_L1, selected, 0, variantForPath(path)); sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1, "StateChanged"_L1, stateArgs); + + // send SelectionChanged event for the parent + QAccessibleInterface* parent = iface->parent(); + if (!parent) { + qCDebug(lcAccessibilityAtspi) << "No valid parent in selection event."; + return; + } + + QString parentPath = pathForInterface(parent); + QVariantList args = packDBusSignalArguments(QString(), 0, 0, variantForPath(parentPath)); + sendDBusSignal(parentPath, QLatin1String(ATSPI_DBUS_INTERFACE_EVENT_OBJECT), + QLatin1String("SelectionChanged"), args); break; } case QAccessible::SelectionWithin: {