From 01f1e10695216993fe86e35adcecc8115a654beb Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Thu, 3 Jul 2014 16:15:21 +0200 Subject: [PATCH] Accessibility Linux: Implement set focus action This is used by Orca for geometric navigation (aka flat review) to move the focus around. It is also generally sensible to be able to programatically move the focus around. This way of moving the focus is redundant with the action interface's focus action. Task-number: QTBUG-40048 Change-Id: I1b61ea843f6bfc3dc00007772e0e5102555ca752 Reviewed-by: Gabriel de Dietrich --- .../linuxaccessibility/atspiadaptor.cpp | 14 +++--- .../tst_qaccessibilitylinux.cpp | 50 +++++++++++++++++++ 2 files changed, 57 insertions(+), 7 deletions(-) diff --git a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp index 60972af70d0..9b76999d178 100644 --- a/src/platformsupport/linuxaccessibility/atspiadaptor.cpp +++ b/src/platformsupport/linuxaccessibility/atspiadaptor.cpp @@ -1639,13 +1639,13 @@ bool AtSpiAdaptor::componentInterface(QAccessibleInterface *interface, const QSt size << rect.width() << rect.height(); connection.send(message.createReply(size)); } else if (function == QLatin1String("GrabFocus")) { -// FIXME: implement focus grabbing -// if (interface->object() && interface->object()->isWidgetType()) { -// QWidget* w = static_cast(interface->object()); -// w->setFocus(Qt::OtherFocusReason); -// sendReply(connection, message, true); -// } - sendReply(connection, message, false); + QAccessibleActionInterface *actionIface = interface->actionInterface(); + if (actionIface && actionIface->actionNames().contains(QAccessibleActionInterface::setFocusAction())) { + actionIface->doAction(QAccessibleActionInterface::setFocusAction()); + sendReply(connection, message, true); + } else { + sendReply(connection, message, false); + } } else if (function == QLatin1String("SetExtents")) { // int x = message.arguments().at(0).toInt(); // int y = message.arguments().at(1).toInt(); diff --git a/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp b/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp index a8313215be9..79e212a65a0 100644 --- a/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp +++ b/tests/auto/other/qaccessibilitylinux/tst_qaccessibilitylinux.cpp @@ -47,6 +47,7 @@ #include #include #include +#include #include #include @@ -102,6 +103,7 @@ private slots: void testTreeWidget(); void testTextEdit(); void testSlider(); + void testFocus(); void cleanupTestCase(); @@ -465,6 +467,54 @@ void tst_QAccessibilityLinux::testSlider() QCOMPARE(valueInterface->property("CurrentValue").toInt(), 4); } +quint64 getAtspiState(QDBusInterface *interface) +{ + QDBusMessage msg = interface->call(QDBus::Block, "GetState"); + const QDBusArgument arg = msg.arguments().at(0).value(); + quint32 state1 = 0; + quint64 state2 = 0; + arg.beginArray(); + arg >> state1; + arg >> state2; + arg.endArray(); + + state2 = state2 << 32; + return state2 | state1; +} + +void tst_QAccessibilityLinux::testFocus() +{ + QLineEdit *lineEdit1 = new QLineEdit(m_window); + lineEdit1->setText("lineEdit 1"); + QLineEdit *lineEdit2 = new QLineEdit(m_window); + lineEdit2->setText("lineEdit 2"); + + m_window->addWidget(lineEdit1); + m_window->addWidget(lineEdit2); + lineEdit1->setFocus(); + + QStringList children = getChildren(mainWindow); + QCOMPARE(children.length(), 2); + QDBusInterface *accessibleInterfaceLineEdit1 = getInterface(children.at(0), "org.a11y.atspi.Accessible"); + QVERIFY(accessibleInterfaceLineEdit1->isValid()); + QDBusInterface *accessibleInterfaceLineEdit2 = getInterface(children.at(1), "org.a11y.atspi.Accessible"); + QVERIFY(accessibleInterfaceLineEdit2->isValid()); + QDBusInterface *componentInterfaceLineEdit1 = getInterface(children.at(0), "org.a11y.atspi.Component"); + QVERIFY(componentInterfaceLineEdit1->isValid()); + QDBusInterface *componentInterfaceLineEdit2 = getInterface(children.at(1), "org.a11y.atspi.Component"); + QVERIFY(componentInterfaceLineEdit2->isValid()); + + quint64 focusedState = quint64(1) << ATSPI_STATE_FOCUSED; + QVERIFY(getAtspiState(accessibleInterfaceLineEdit1) & focusedState); + QVERIFY(!(getAtspiState(accessibleInterfaceLineEdit2) & focusedState)); + + QDBusMessage focusReply = componentInterfaceLineEdit2->call(QDBus::Block, "GrabFocus"); + QVERIFY(focusReply.arguments().at(0).toBool()); + QVERIFY(lineEdit2->hasFocus()); + QVERIFY(!(getAtspiState(accessibleInterfaceLineEdit1) & focusedState)); + QVERIFY(getAtspiState(accessibleInterfaceLineEdit2) & focusedState); +} + QTEST_MAIN(tst_QAccessibilityLinux) #include "tst_qaccessibilitylinux.moc"