a11y atspi: Send SelectionChanged AT-SPI event on selection change

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ø <tor.arne.vestbo@qt.io>
This commit is contained in:
Michael Weghorn 2022-08-26 15:52:40 +02:00
parent 2910a6b308
commit 063344c8b9

View File

@ -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: {