From 1b0e76f514e9a460e1d78a813813c0909838a03e Mon Sep 17 00:00:00 2001 From: Michael Weghorn Date: Mon, 2 Oct 2023 23:09:06 +0200 Subject: [PATCH] a11y atspi: Don't restrict top-level window to 2 a11y roles So far, only accessible interfaces of roles QAccessible::Dialog and QAccessible::Window were taken into account when trying to find the top-level window in order to calculate the window-relative coordinates relative to that one. However, an app doesn't necessarily need to have any such widget/ window as it's top-level object, but can have any widget there. Therefore, consider any a11y object that is a direct child of the application's a11y object a top-level window as well. For example, in the spinboxes example (qtbase/examples/widgets/widgets/spinboxes/spinboxes), the top-level widget is a QGroupBox, which has an accessible role of QAccessible::Client, which maps to ATSPI_ROLE_FILLER for AT-SPI on Linux. Since that's the top-level widget, window-relative coordinates should be calculated relative to it. (Without this change in place, screen coordinates would be used for the window-relative coordinates as well, as found by the script attached to QTBUG-106527.) Also deduplicate a bit and just have a single loop instead of the extra check on the interface itself at the beginning. Fixes: QTBUG-106527 Pick-to: 6.6 6.5 Change-Id: I8d2a00bcc22c71d696e4f48233afddc80e93bc1b Reviewed-by: Volker Hilsheimer --- src/gui/accessible/linux/atspiadaptor.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/gui/accessible/linux/atspiadaptor.cpp b/src/gui/accessible/linux/atspiadaptor.cpp index 885d4d9144..377010fd6d 100644 --- a/src/gui/accessible/linux/atspiadaptor.cpp +++ b/src/gui/accessible/linux/atspiadaptor.cpp @@ -1750,15 +1750,14 @@ bool AtSpiAdaptor::inheritsQAction(QObject *object) // Component static QAccessibleInterface * getWindow(QAccessibleInterface * interface) { - if (interface->role() == QAccessible::Dialog || interface->role() == QAccessible::Window) - return interface; + // find top-level window in a11y hierarchy (either has a + // corresponding role or is a direct child of the application object) + QAccessibleInterface* app = QAccessible::queryAccessibleInterface(qApp); + while (interface && interface->role() != QAccessible::Dialog + && interface->role() != QAccessible::Window && interface->parent() != app) + interface = interface->parent(); - QAccessibleInterface * parent = interface->parent(); - while (parent && parent->role() != QAccessible::Dialog - && parent->role() != QAccessible::Window) - parent = parent->parent(); - - return parent; + return interface; } bool AtSpiAdaptor::componentInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection)