diff options
Diffstat (limited to 'tests/auto/other/qaccessibility/tst_qaccessibility.cpp')
-rw-r--r-- | tests/auto/other/qaccessibility/tst_qaccessibility.cpp | 366 |
1 files changed, 320 insertions, 46 deletions
diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp index c54d9308c4..5fd695e2e6 100644 --- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp @@ -1,12 +1,11 @@ // Copyright (C) 2016 The Qt Company Ltd. -// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 - +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only #include <QtCore/qglobal.h> #ifdef Q_OS_WIN # include <QtCore/qt_windows.h> # include <oleacc.h> -# include <QtGui/private/qwindowsuiawrapper_p.h> +# include <uiautomation.h> # include <servprov.h> # include <winuser.h> #endif @@ -40,6 +39,7 @@ #include <QtTest/private/qtesthelpers_p.h> using namespace QTestPrivate; +using namespace Qt::StringLiterals; static inline bool verifyChild(QWidget *child, QAccessibleInterface *interface, int index, const QRect &domain) @@ -214,6 +214,7 @@ private slots: void listTest(); void treeTest(); void tableTest(); + void rootIndexView(); void uniqueIdTest(); void calendarWidgetTest(); @@ -222,6 +223,7 @@ private slots: void accessibleName(); #if QT_CONFIG(shortcut) void labelTest(); + void relationTest(); void accelerators(); #endif void bridgeTest(); @@ -298,9 +300,9 @@ void tst_QAccessibility::cleanup() { const EventList list = QTestAccessibility::events(); if (!list.isEmpty()) { - qWarning("%zd accessibility event(s) were not handled in testfunction '%s':", size_t(list.count()), + qWarning("%zd accessibility event(s) were not handled in testfunction '%s':", size_t(list.size()), QString(QTest::currentTestFunction()).toLatin1().constData()); - for (int i = 0; i < list.count(); ++i) + for (int i = 0; i < list.size(); ++i) qWarning(" %d: Object: %p Event: '%s' Child: %d", i + 1, list.at(i)->object(), qAccessibleEventString(list.at(i)->type()), list.at(i)->child()); } @@ -663,7 +665,7 @@ void tst_QAccessibility::textAttributes_data() defaultComplexFont.setStyle(QFont::StyleItalic); defaultComplexFont.setUnderline(true); - static QStringList defaults = QString("font-style:normal;font-weight:normal;text-align:left;text-position:baseline;font-size:13pt").split(';'); + static QStringList defaults = QString("font-style:normal;font-weight:normal;text-align:left;text-position:baseline;font-size:13pt;text-line-through-type:none").split(';'); static QStringList bold = defaults; bold[1] = QString::fromLatin1("font-weight:bold"); @@ -699,7 +701,7 @@ void tst_QAccessibility::textAttributes_data() defaultFontDifferentBoldItalic[1] = QString::fromLatin1("font-weight:bold"); static QStringList defaultFontDifferentMonospace = defaultFontDifferent; - defaultFontDifferentMonospace[7] = (QLatin1String("font-family:\"monospace\"")); + defaultFontDifferentMonospace[8] = (QLatin1String("font-family:\"monospace\"")); static QStringList defaultFontDifferentFont8pt = defaultFontDifferent; defaultFontDifferentFont8pt[4] = (QLatin1String("font-size:8pt")); @@ -786,7 +788,7 @@ void tst_QAccessibility::textAttributes() QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&textEdit); QAccessibleTextInterface *textInterface=interface->textInterface(); QVERIFY(textInterface); - QCOMPARE(textInterface->characterCount(), textEdit.toPlainText().length()); + QCOMPARE(textInterface->characterCount(), textEdit.toPlainText().size()); int startOffset = -1; int endOffset = -1; @@ -1117,7 +1119,10 @@ void tst_QAccessibility::buttonTest() interface = QAccessible::queryAccessibleInterface(&toggleButton); actionInterface = interface->actionInterface(); QCOMPARE(interface->role(), QAccessible::CheckBox); - QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::toggleAction() << QAccessibleActionInterface::setFocusAction()); + QCOMPARE(actionInterface->actionNames(), + QStringList() << QAccessibleActionInterface::toggleAction() + << QAccessibleActionInterface::pressAction() + << QAccessibleActionInterface::setFocusAction()); QCOMPARE(actionInterface->localizedActionDescription(QAccessibleActionInterface::toggleAction()), QString("Toggles the state")); QVERIFY(!toggleButton.isChecked()); QVERIFY(!interface->state().checked); @@ -1153,12 +1158,18 @@ void tst_QAccessibility::buttonTest() interface = QAccessible::queryAccessibleInterface(&checkBox); actionInterface = interface->actionInterface(); QCOMPARE(interface->role(), QAccessible::CheckBox); - QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::toggleAction() << QAccessibleActionInterface::setFocusAction()); + QCOMPARE(actionInterface->actionNames(), + QStringList() << QAccessibleActionInterface::toggleAction() + << QAccessibleActionInterface::pressAction() + << QAccessibleActionInterface::setFocusAction()); QVERIFY(!interface->state().checked); actionInterface->doAction(QAccessibleActionInterface::toggleAction()); QTest::qWait(500); - QCOMPARE(actionInterface->actionNames(), QStringList() << QAccessibleActionInterface::toggleAction() << QAccessibleActionInterface::setFocusAction()); + QCOMPARE(actionInterface->actionNames(), + QStringList() << QAccessibleActionInterface::toggleAction() + << QAccessibleActionInterface::pressAction() + << QAccessibleActionInterface::setFocusAction()); QVERIFY(interface->state().checked); QVERIFY(checkBox.isChecked()); QAccessible::State st; @@ -1948,7 +1959,7 @@ void tst_QAccessibility::mdiAreaTest() mdiArea.addSubWindow(new QWidget, Qt::Dialog)->show(); QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList(); - QCOMPARE(subWindows.count(), subWindowCount); + QCOMPARE(subWindows.size(), subWindowCount); QAccessibleInterface *interface = QAccessible::queryAccessibleInterface(&mdiArea); QVERIFY(interface); @@ -1986,7 +1997,7 @@ void tst_QAccessibility::mdiSubWindowTest() } QList<QMdiSubWindow *> subWindows = mdiArea.subWindowList(); - QCOMPARE(subWindows.count(), subWindowCount); + QCOMPARE(subWindows.size(), subWindowCount); QMdiSubWindow *testWindow = subWindows.at(3); QVERIFY(testWindow); @@ -2110,10 +2121,10 @@ void tst_QAccessibility::lineEditTest() QCOMPARE(iface->text(QAccessible::Value), QString()); le->setEchoMode(QLineEdit::Password); QVERIFY(iface->state().passwordEdit); - QCOMPARE(iface->text(QAccessible::Value), QString(secret.length(), QLatin1Char('*'))); + QCOMPARE(iface->text(QAccessible::Value), QString(secret.size(), QLatin1Char('*'))); le->setEchoMode(QLineEdit::PasswordEchoOnEdit); QVERIFY(iface->state().passwordEdit); - QCOMPARE(iface->text(QAccessible::Value), QString(secret.length(), QLatin1Char('*'))); + QCOMPARE(iface->text(QAccessible::Value), QString(secret.size(), QLatin1Char('*'))); le->setEchoMode(QLineEdit::Normal); QVERIFY(!(iface->state().passwordEdit)); QCOMPARE(iface->text(QAccessible::Value), secret); @@ -2205,7 +2216,7 @@ void tst_QAccessibility::lineEditTest() QCOMPARE(textIface->textAtOffset(5, QAccessible::ParagraphBoundary,&start,&end), cite); QCOMPARE(start, 0); - QCOMPARE(end, cite.length()); + QCOMPARE(end, cite.size()); QCOMPARE(textIface->textAtOffset(5, QAccessible::LineBoundary,&start,&end), cite); QCOMPARE(textIface->textAtOffset(5, QAccessible::NoBoundary,&start,&end), cite); @@ -2249,8 +2260,8 @@ void tst_QAccessibility::lineEditTest() QVERIFY_EVENT(&sel); lineEdit->selectAll(); - sel.setSelection(0, lineEdit->text().length()); - sel.setCursorPosition(lineEdit->text().length()); + sel.setSelection(0, lineEdit->text().size()); + sel.setCursorPosition(lineEdit->text().size()); QVERIFY_EVENT(&sel); lineEdit->setSelection(10, -4); @@ -2606,7 +2617,7 @@ void tst_QAccessibility::dialogButtonBoxTest() std::sort(buttons.begin(), buttons.end(), accessibleInterfaceLeftOf); - for (int i = 0; i < buttons.count(); ++i) + for (int i = 0; i < buttons.size(); ++i) actualOrder << buttons.at(i)->text(QAccessible::Name); QStringList expectedOrder; @@ -2658,7 +2669,7 @@ void tst_QAccessibility::dialogButtonBoxTest() std::sort(buttons.begin(), buttons.end(), accessibleInterfaceAbove); - for (int i = 0; i < buttons.count(); ++i) + for (int i = 0; i < buttons.size(); ++i) actualOrder << buttons.at(i)->text(QAccessible::Name); QStringList expectedOrder; @@ -2868,6 +2879,12 @@ void tst_QAccessibility::listTest() QCOMPARE(iface->indexOfChild(child3), 2); QCOMPARE(child3->text(QAccessible::Name), QString("Brisbane")); } + + // Check that application is accessible parent, since it's a top-level widget + QAccessibleInterface *parentIface = iface->parent(); + QVERIFY(parentIface); + QVERIFY(parentIface->role() == QAccessible::Application); + QTestAccessibility::clearEvents(); // Check for events @@ -2919,7 +2936,8 @@ void tst_QAccessibility::listTest() QVERIFY(!(cell4->state().expandable)); QVERIFY( (cell4->state().selectable)); QVERIFY(!(cell4->state().selected)); - table2->selectRow(3); + QAccessibleSelectionInterface *selection2 = iface->selectionInterface(); + selection2->select(cell4); QCOMPARE(listView->selectedItems().size(), 1); QCOMPARE(listView->selectedItems().at(0)->text(), QLatin1String("Munich")); QVERIFY(cell4->state().selected); @@ -3390,6 +3408,51 @@ void tst_QAccessibility::tableTest() QTestAccessibility::clearEvents(); } +void tst_QAccessibility::rootIndexView() +{ + QStandardItemModel model; + for (int i = 0; i < 2; ++i) { + QStandardItem *item = new QStandardItem(u"root %1"_s.arg(i)); + for (int j = 0; j < 5 * (i + 1); ++j) { + switch (i) { + case 0: + item->appendRow(new QStandardItem(u"child0/%1"_s.arg(j))); + break; + case 1: + item->appendRow({new QStandardItem(u"column0 1/%1"_s.arg(j)), + new QStandardItem(u"column1 1/%1"_s.arg(j)) + }); + break; + } + } + model.appendRow(item); + } + + QListView view; + view.setModel(&model); + QTestAccessibility::clearEvents(); + + QAccessibleInterface *accView = QAccessible::queryAccessibleInterface(&view); + QVERIFY(accView); + QAccessibleTableInterface *accTable = accView->tableInterface(); + QVERIFY(accTable); + QCOMPARE(accTable->rowCount(), 2); + QCOMPARE(accTable->columnCount(), 1); + + view.setRootIndex(model.index(0, 0)); + QAccessibleTableModelChangeEvent resetEvent(&view, QAccessibleTableModelChangeEvent::ModelReset); + QVERIFY(QTestAccessibility::containsEvent(&resetEvent)); + + QCOMPARE(accTable->rowCount(), 5); + QCOMPARE(accTable->columnCount(), 1); + + view.setRootIndex(model.index(1, 0)); + QCOMPARE(accTable->rowCount(), 10); + QCOMPARE(accTable->columnCount(), 2); + + QTestAccessibility::clearEvents(); +} + void tst_QAccessibility::uniqueIdTest() { // Test that an ID isn't reassigned to another interface right away when an accessible interface @@ -3436,7 +3499,7 @@ void tst_QAccessibility::calendarWidgetTest() QCOMPARE(interface->rect(), globalGeometry); QWidget *navigationBar = 0; - foreach (QObject *child, calendarWidget.children()) { + for (QObject *child : calendarWidget.children()) { if (child->objectName() == QLatin1String("qt_calendar_navigationbar")) { navigationBar = static_cast<QWidget *>(child); break; @@ -3446,7 +3509,7 @@ void tst_QAccessibility::calendarWidgetTest() QVERIFY(verifyChild(navigationBar, interface, 0, globalGeometry)); QAbstractItemView *calendarView = 0; - foreach (QObject *child, calendarWidget.children()) { + for (QObject *child : calendarWidget.children()) { if (child->objectName() == QLatin1String("qt_calendar_calendarview")) { calendarView = static_cast<QAbstractItemView *>(child); break; @@ -3648,6 +3711,8 @@ void tst_QAccessibility::comboBoxTest() QCOMPARE(iface->text(QAccessible::Name), QLatin1String("one")); #endif QCOMPARE(iface->text(QAccessible::Value), QLatin1String("one")); + QCOMPARE(combo.view()->selectionModel()->currentIndex().row(), 0); + combo.setCurrentIndex(2); #ifdef Q_OS_UNIX QCOMPARE(iface->text(QAccessible::Name), QLatin1String("three")); @@ -3658,7 +3723,13 @@ void tst_QAccessibility::comboBoxTest() QCOMPARE(listIface->role(), QAccessible::List); QCOMPARE(listIface->childCount(), 3); + QAccessibleSelectionInterface *selectionIface = listIface->selectionInterface(); + QVERIFY(selectionIface); + QCOMPARE(selectionIface->selectedItemCount(), 1); + QCOMPARE(listIface->indexOfChild(selectionIface->selectedItem(0)), 2); + QVERIFY(!combo.view()->isVisible()); + QCOMPARE(combo.view()->selectionModel()->currentIndex().row(), 2); QVERIFY(iface->actionInterface()); QCOMPARE(iface->actionInterface()->actionNames(), QStringList() << QAccessibleActionInterface::showMenuAction() << QAccessibleActionInterface::pressAction()); iface->actionInterface()->doAction(QAccessibleActionInterface::showMenuAction()); @@ -3688,6 +3759,69 @@ void tst_QAccessibility::comboBoxTest() QTestAccessibility::clearEvents(); } +void tst_QAccessibility::relationTest() +{ + auto windowHolder = std::make_unique<QWidget>(); + auto window = windowHolder.get(); + QString text = "Hello World"; + QLabel *label = new QLabel(text, window); + setFrameless(label); + QSpinBox *spinBox = new QSpinBox(window); + label->setBuddy(spinBox); + QProgressBar *pb = new QProgressBar(window); + pb->setRange(0, 99); + connect(spinBox, SIGNAL(valueChanged(int)), pb, SLOT(setValue(int))); + + window->resize(320, 200); + window->show(); + + QVERIFY(QTest::qWaitForWindowExposed(window)); +#if defined(Q_OS_UNIX) + QCoreApplication::processEvents(); +#endif + QTest::qWait(100); + + QAccessibleInterface *acc_label = QAccessible::queryAccessibleInterface(label); + QVERIFY(acc_label); + QAccessibleInterface *acc_spinBox = QAccessible::queryAccessibleInterface(spinBox); + QVERIFY(acc_spinBox); + QAccessibleInterface *acc_pb = QAccessible::queryAccessibleInterface(pb); + QVERIFY(acc_pb); + + typedef QPair<QAccessibleInterface*, QAccessible::Relation> RelationPair; + { + const QList<RelationPair> rels = acc_label->relations(QAccessible::Labelled); + QCOMPARE(rels.size(), 1); + const RelationPair relPair = rels.first(); + + // spinBox is Labelled by acc_label + QCOMPARE(relPair.first->object(), spinBox); + QCOMPARE(relPair.second, QAccessible::Labelled); + } + + { + // Test multiple relations (spinBox have two) + const QList<RelationPair> rels = acc_spinBox->relations(); + QCOMPARE(rels.size(), 2); + int visitCount = 0; + for (const auto &relPair : rels) { + if (relPair.second & QAccessible::Label) { + // label is the Label of spinBox + QCOMPARE(relPair.first->object(), label); + ++visitCount; + } else if (relPair.second & QAccessible::Controlled) { + // progressbar is Controlled by the spinBox + QCOMPARE(relPair.first->object(), pb); + ++visitCount; + } + } + QCOMPARE(visitCount, rels.size()); + } + + windowHolder.reset(); + QTestAccessibility::clearEvents(); +} + #if QT_CONFIG(shortcut) void tst_QAccessibility::labelTest() @@ -3710,6 +3844,8 @@ void tst_QAccessibility::labelTest() QAccessibleInterface *acc_label = QAccessible::queryAccessibleInterface(label); QVERIFY(acc_label); + QAccessibleInterface *acc_lineEdit = QAccessible::queryAccessibleInterface(buddy); + QVERIFY(acc_lineEdit); QCOMPARE(acc_label->text(QAccessible::Name), text); QCOMPARE(acc_label->state().editable, false); @@ -3719,13 +3855,23 @@ void tst_QAccessibility::labelTest() QCOMPARE(acc_label->state().focusable, false); QCOMPARE(acc_label->state().readOnly, true); - QList<QPair<QAccessibleInterface *, QAccessible::Relation>> rels = acc_label->relations(); - QCOMPARE(rels.count(), 1); - QAccessibleInterface *iface = rels.first().first; - QAccessible::Relation rel = rels.first().second; - QCOMPARE(rel, QAccessible::Labelled); - QCOMPARE(iface->role(), QAccessible::EditableText); + typedef QPair<QAccessibleInterface*, QAccessible::Relation> RelationPair; + { + const QList<RelationPair> rels = acc_label->relations(QAccessible::Labelled); + QCOMPARE(rels.size(), 1); + const RelationPair relPair = rels.first(); + QCOMPARE(relPair.first->object(), buddy); + QCOMPARE(relPair.second, QAccessible::Labelled); + } + + { + const QList<RelationPair> rels = acc_lineEdit->relations(QAccessible::Label); + QCOMPARE(rels.size(), 1); + const RelationPair relPair = rels.first(); + QCOMPARE(relPair.first->object(), label); + QCOMPARE(relPair.second, QAccessible::Label); + } windowHolder.reset(); QTestAccessibility::clearEvents(); @@ -3821,6 +3967,7 @@ void tst_QAccessibility::bridgeTest() // For now this is a simple test to see if the bridge is working at all. // Ideally it should be extended to test all aspects of the bridge. #if defined(Q_OS_WIN) + auto guard = qScopeGuard([]() { QTestAccessibility::clearEvents(); }); QWidget window; QVBoxLayout *lay = new QVBoxLayout(&window); @@ -3958,10 +4105,105 @@ void tst_QAccessibility::bridgeTest() QCOMPARE(controlTypeId, UIA_ButtonControlTypeId); // Edit - hr = nodeList.at(2)->get_CurrentControlType(&controlTypeId); + IUIAutomationElement *uiaElement = nodeList.at(2); + hr = uiaElement->get_CurrentControlType(&controlTypeId); QVERIFY(SUCCEEDED(hr)); QCOMPARE(controlTypeId, UIA_EditControlTypeId); + // "hello world\nhow are you today?\n" + IUIAutomationTextPattern *textPattern = nullptr; + hr = uiaElement->GetCurrentPattern(UIA_TextPattern2Id, reinterpret_cast<IUnknown**>(&textPattern)); + QVERIFY(SUCCEEDED(hr)); + QVERIFY(textPattern); + + IUIAutomationTextRange *docRange = nullptr; + hr = textPattern->get_DocumentRange(&docRange); + QVERIFY(SUCCEEDED(hr)); + QVERIFY(docRange); + + IUIAutomationTextRange *textRange = nullptr; + hr = docRange->Clone(&textRange); + QVERIFY(SUCCEEDED(hr)); + QVERIFY(textRange); + int moved; + + auto rangeText = [](IUIAutomationTextRange *textRange) { + BSTR str; + QString res = "IUIAutomationTextRange::GetText() failed"; + HRESULT hr = textRange->GetText(-1, &str); + if (SUCCEEDED(hr)) { + res = QString::fromWCharArray(str); + ::SysFreeString(str); + } + return res; + }; + + // Move start endpoint past "hello " to "world" + hr = textRange->Move(TextUnit_Character, 6, &moved); + QVERIFY(SUCCEEDED(hr)); + QCOMPARE(moved, 6); + // If the range was not empty, it should be collapsed to contain a single text unit + QCOMPARE(rangeText(textRange), QString("w")); + + // Move end endpoint to end of "world" + hr = textRange->MoveEndpointByUnit(TextPatternRangeEndpoint_End, TextUnit_Character, 4, &moved); + QVERIFY(SUCCEEDED(hr)); + QCOMPARE(moved, 4); + QCOMPARE(rangeText(textRange), QString("world")); + + // MSDN: "Zero has no effect". This behavior was also verified with native controls. + hr = textRange->Move(TextUnit_Character, 0, &moved); + QVERIFY(SUCCEEDED(hr)); + QCOMPARE(moved, 0); + QCOMPARE(rangeText(textRange), QString("world")); + + hr = textRange->Move(TextUnit_Character, 1, &moved); + QVERIFY(SUCCEEDED(hr)); + QCOMPARE(rangeText(textRange), QString("o")); + + // move as far towards the end as possible + hr = textRange->Move(TextUnit_Character, 999, &moved); + QVERIFY(SUCCEEDED(hr)); + QCOMPARE(rangeText(textRange), QString("")); + + hr = textRange->MoveEndpointByUnit(TextPatternRangeEndpoint_Start, TextUnit_Character, -1, &moved); + QVERIFY(SUCCEEDED(hr)); + QCOMPARE(rangeText(textRange), QString("\n")); + + // move one forward (last possible position again) + hr = textRange->Move(TextUnit_Character, 1, &moved); + QVERIFY(SUCCEEDED(hr)); + QCOMPARE(rangeText(textRange), QString("")); + + hr = textRange->Move(TextUnit_Character, -7, &moved); + QVERIFY(SUCCEEDED(hr)); + QCOMPARE(moved, -7); + QCOMPARE(rangeText(textRange), QString("")); + // simulate moving cursor (empty range) towards (and past) the end + QString today(" today?\n"); + for (int i = 1; i < 9; ++i) { // 9 is deliberately too much + // peek one character back + hr = textRange->MoveEndpointByUnit(TextPatternRangeEndpoint_Start, TextUnit_Character, -1, &moved); + QVERIFY(SUCCEEDED(hr)); + QCOMPARE(rangeText(textRange), today.mid(i - 1, 1)); + + hr = textRange->Move(TextUnit_Character, 1, &moved); + QVERIFY(SUCCEEDED(hr)); + QCOMPARE(rangeText(textRange), today.mid(i, moved)); // when we cannot move further, moved will be 0 + + // Make the range empty again + hr = textRange->MoveEndpointByUnit(TextPatternRangeEndpoint_End, TextUnit_Character, -moved, &moved); + QVERIFY(SUCCEEDED(hr)); + + // advance the empty range + hr = textRange->Move(TextUnit_Character, 1, &moved); + QVERIFY(SUCCEEDED(hr)); + } + docRange->Release(); + textRange->Release(); + textPattern->Release(); + + // Table hr = nodeList.at(3)->get_CurrentControlType(&controlTypeId); QVERIFY(SUCCEEDED(hr)); @@ -3979,8 +4221,6 @@ void tst_QAccessibility::bridgeTest() controlWalker->Release(); windowElement->Release(); automation->Release(); - - QTestAccessibility::clearEvents(); #endif } @@ -4071,6 +4311,9 @@ private: void tst_QAccessibility::focusChild() { + if (!QGuiApplicationPrivate::platformIntegration()->hasCapability(QPlatformIntegration::WindowActivation)) + QSKIP("Platform does not support window activation"); + { QMainWindow mainWindow; QtTestAccessibleWidget *widget1 = new QtTestAccessibleWidget(0, "Widget1"); @@ -4176,7 +4419,7 @@ void tst_QAccessibility::focusChild() spy.clear(); tableView->setCurrentCell(2, 1); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); QAccessibleInterface *child = iface->focusChild(); QVERIFY(child); @@ -4184,7 +4427,7 @@ void tst_QAccessibility::focusChild() spy.clear(); tableView->setCurrentCell(1, 2); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); child = iface->focusChild(); QVERIFY(child); @@ -4236,7 +4479,7 @@ void tst_QAccessibility::focusChild() spy.clear(); treeView->setCurrentItem(item2); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); QAccessibleInterface *child = iface->focusChild(); QVERIFY(child); @@ -4244,12 +4487,53 @@ void tst_QAccessibility::focusChild() spy.clear(); treeView->setCurrentItem(item3); - QTRY_COMPARE(spy.count(), 1); + QTRY_COMPARE(spy.size(), 1); child = iface->focusChild(); QVERIFY(child); QCOMPARE(child->text(QAccessible::Name), QStringLiteral("Klimt")); } + { + QWidget window; + // takes the initial focus + QLineEdit lineEdit; + QComboBox comboBox; + comboBox.addItems({"One", "Two", "Three"}); + QComboBox editableComboBox; + editableComboBox.setEditable(true); + editableComboBox.addItems({"A", "B", "C"}); + QVBoxLayout vbox; + vbox.addWidget(&lineEdit); + vbox.addWidget(&comboBox); + vbox.addWidget(&editableComboBox); + window.setLayout(&vbox); + + window.show(); + QVERIFY(QTest::qWaitForWindowExposed(&window)); + QTestAccessibility::clearEvents(); + QAccessibleInterface *iface = nullptr; + + comboBox.setFocus(); + { + QAccessibleEvent focusEvent(&comboBox, QAccessible::Focus); + QVERIFY(QTestAccessibility::containsEvent(&focusEvent)); + } + iface = QAccessible::queryAccessibleInterface(&comboBox); + QVERIFY(iface); + QCOMPARE(iface->focusChild(), nullptr); + + editableComboBox.setFocus(); + // Qt updates about the editable combobox, not the lineedit, as the + // combobox is the lineedit's focus proxy. + { + QAccessibleEvent focusEvent(&editableComboBox, QAccessible::Focus); + QVERIFY(QTestAccessibility::containsEvent(&focusEvent)); + } + iface = QAccessible::queryAccessibleInterface(&editableComboBox); + QVERIFY(iface); + QVERIFY(iface->focusChild()); + QCOMPARE(iface->focusChild()->role(), QAccessible::EditableText); + } } void tst_QAccessibility::messageBoxTest_data() @@ -4339,20 +4623,10 @@ void tst_QAccessibility::messageBoxTest() if (!boxPrivate->canBeNativeDialog()) { // platforms that use a native message box will not emit accessibility events box.show(); - QVERIFY(QTest::qWaitForWindowActive(&box)); QAccessibleEvent showEvent(&box, QAccessible::DialogStart); QVERIFY(QTestAccessibility::containsEvent(&showEvent)); - // on some platforms, like macOS, not all widgets get key board focus; we - // only care about a push button getting focus - if (QTest::qWaitFor([&box]{ return qobject_cast<QPushButton *>(box.focusWidget()); }, 1000)) { - // a widget that gets focus through window activation should not emit an accessibility - // notification - QAccessibleEvent focusEvent(box.focusWidget(), QAccessible::Focus); - QVERIFY(!QTestAccessibility::containsEvent(&focusEvent)); - } - box.hide(); QAccessibleEvent hideEvent(&box, QAccessible::DialogEnd); |