a11y: support GetAccessibleId for at-spi
This introduces a new helper function accessibleIdForAccessible (inspired by Windows' automationIdForAccessible) to synthesize an id out of the objectNames of the accessible parent chain. The id is then exposed via the GetAccessibleId D-Bus function for consumption in a11y tools. Change-Id: If72b86c5864c43f4ca842aa11423dd8aea0dde4a Reviewed-by: Aleix Pol Gonzalez <aleixpol@kde.org>
This commit is contained in:
parent
c938752bd1
commit
75e8754875
@ -167,6 +167,9 @@ QString AtSpiAdaptor::introspect(const QString &path) const
|
|||||||
" <arg direction=\"out\" type=\"(so)\"/>\n"
|
" <arg direction=\"out\" type=\"(so)\"/>\n"
|
||||||
" <annotation value=\"QSpiObjectReference\" name=\"org.qtproject.QtDBus.QtTypeName.Out0\"/>\n"
|
" <annotation value=\"QSpiObjectReference\" name=\"org.qtproject.QtDBus.QtTypeName.Out0\"/>\n"
|
||||||
" </method>\n"
|
" </method>\n"
|
||||||
|
" <method name=\"GetAccessibleId\">\n"
|
||||||
|
" <arg direction=\"out\" type=\"s\"/>\n"
|
||||||
|
" </method>\n"
|
||||||
" </interface>\n"
|
" </interface>\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1467,6 +1470,26 @@ void AtSpiAdaptor::registerApplication()
|
|||||||
delete registry;
|
delete registry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
QString accessibleIdForAccessible(QAccessibleInterface *accessible)
|
||||||
|
{
|
||||||
|
QString result;
|
||||||
|
while (accessible) {
|
||||||
|
if (!result.isEmpty())
|
||||||
|
result.prepend(u'.');
|
||||||
|
if (auto obj = accessible->object()) {
|
||||||
|
const QString name = obj->objectName();
|
||||||
|
if (!name.isEmpty())
|
||||||
|
result.prepend(name);
|
||||||
|
else
|
||||||
|
result.prepend(QString::fromUtf8(obj->metaObject()->className()));
|
||||||
|
}
|
||||||
|
accessible = accessible->parent();
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
} // namespace
|
||||||
|
|
||||||
// Accessible
|
// Accessible
|
||||||
bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection)
|
bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QString &function, const QDBusMessage &message, const QDBusConnection &connection)
|
||||||
{
|
{
|
||||||
@ -1553,6 +1576,9 @@ bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QS
|
|||||||
children << ref;
|
children << ref;
|
||||||
}
|
}
|
||||||
connection.send(message.createReply(QVariant::fromValue(children)));
|
connection.send(message.createReply(QVariant::fromValue(children)));
|
||||||
|
} else if (function == "GetAccessibleId"_L1) {
|
||||||
|
sendReply(connection, message,
|
||||||
|
QVariant::fromValue(QDBusVariant(accessibleIdForAccessible(interface))));
|
||||||
} else {
|
} else {
|
||||||
qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::accessibleInterface does not implement " << function << message.path();
|
qCDebug(lcAccessibilityAtspi) << "WARNING: AtSpiAdaptor::accessibleInterface does not implement " << function << message.path();
|
||||||
return false;
|
return false;
|
||||||
|
@ -154,6 +154,7 @@ void tst_QAccessibilityLinux::initTestCase()
|
|||||||
QVERIFY(!address.isEmpty());
|
QVERIFY(!address.isEmpty());
|
||||||
|
|
||||||
m_window = new AccessibleTestWindow();
|
m_window = new AccessibleTestWindow();
|
||||||
|
m_window->setObjectName("mainWindow"_L1);
|
||||||
m_window->show();
|
m_window->show();
|
||||||
|
|
||||||
QVERIFY(QTest::qWaitForWindowExposed(m_window));
|
QVERIFY(QTest::qWaitForWindowExposed(m_window));
|
||||||
@ -211,8 +212,11 @@ bool hasState(QDBusInterface *interface, AtspiStateType state)
|
|||||||
void tst_QAccessibilityLinux::testLabel()
|
void tst_QAccessibilityLinux::testLabel()
|
||||||
{
|
{
|
||||||
QLabel *l = new QLabel(m_window);
|
QLabel *l = new QLabel(m_window);
|
||||||
|
l->setObjectName("theObjectName"_L1);
|
||||||
l->setText("Hello A11y");
|
l->setText("Hello A11y");
|
||||||
m_window->addWidget(l);
|
m_window->addWidget(l);
|
||||||
|
auto a11yEmpty = new QLabel(m_window);
|
||||||
|
m_window->addWidget(l);
|
||||||
|
|
||||||
// Application
|
// Application
|
||||||
QCOMPARE(getParent(mainWindow), QLatin1String(ATSPI_DBUS_PATH_ROOT));
|
QCOMPARE(getParent(mainWindow), QLatin1String(ATSPI_DBUS_PATH_ROOT));
|
||||||
@ -224,6 +228,8 @@ void tst_QAccessibilityLinux::testLabel()
|
|||||||
QCOMPARE(getChildren(labelInterface).count(), 0);
|
QCOMPARE(getChildren(labelInterface).count(), 0);
|
||||||
QCOMPARE(labelInterface->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("label"));
|
QCOMPARE(labelInterface->call(QDBus::Block, "GetRoleName").arguments().first().toString(), QLatin1String("label"));
|
||||||
QCOMPARE(labelInterface->call(QDBus::Block, "GetRole").arguments().first().toUInt(), 29u);
|
QCOMPARE(labelInterface->call(QDBus::Block, "GetRole").arguments().first().toUInt(), 29u);
|
||||||
|
QCOMPARE(labelInterface->call(QDBus::Block, "GetAccessibleId").arguments().first().toString(),
|
||||||
|
"mainWindow.theObjectName"_L1);
|
||||||
QCOMPARE(getParent(labelInterface), mainWindow->path());
|
QCOMPARE(getParent(labelInterface), mainWindow->path());
|
||||||
QVERIFY(!hasState(labelInterface, ATSPI_STATE_EDITABLE));
|
QVERIFY(!hasState(labelInterface, ATSPI_STATE_EDITABLE));
|
||||||
QVERIFY(hasState(labelInterface, ATSPI_STATE_READ_ONLY));
|
QVERIFY(hasState(labelInterface, ATSPI_STATE_READ_ONLY));
|
||||||
@ -231,7 +237,12 @@ void tst_QAccessibilityLinux::testLabel()
|
|||||||
l->setText("New text");
|
l->setText("New text");
|
||||||
QCOMPARE(labelInterface->property("Name").toString(), l->text());
|
QCOMPARE(labelInterface->property("Name").toString(), l->text());
|
||||||
|
|
||||||
|
auto *a11yEmptyInterface = getInterface(children.at(1), "org.a11y.atspi.Accessible");
|
||||||
|
QCOMPARE(a11yEmptyInterface->call(QDBus::Block, "GetAccessibleId").arguments().first().toString(),
|
||||||
|
"mainWindow.QLabel"_L1);
|
||||||
|
|
||||||
m_window->clearChildren();
|
m_window->clearChildren();
|
||||||
|
delete a11yEmptyInterface;
|
||||||
delete labelInterface;
|
delete labelInterface;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user