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 <gabriel.dedietrich@digia.com>
This commit is contained in:
Frederik Gladhorn 2014-07-03 16:15:21 +02:00
parent 9c79f6dfb3
commit 01f1e10695
2 changed files with 57 additions and 7 deletions

View File

@ -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<QWidget*>(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();

View File

@ -47,6 +47,7 @@
#include <QtWidgets/QListWidget>
#include <QtWidgets/QTreeWidget>
#include <QtWidgets/QTextEdit>
#include <QtWidgets/QPushButton>
#include <QDBusArgument>
#include <QDBusConnection>
@ -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<QDBusArgument>();
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"