From d2a71d032497a424ece3f77887d7ec9007c70869 Mon Sep 17 00:00:00 2001 From: Michael Weghorn Date: Tue, 26 Sep 2023 21:11:18 +0200 Subject: [PATCH] a11y: Keep current combobox entry in sync When changing the selected index in a combo box, also update the current index in the item view's selection model right away, and don't delay this until when the combobox popup gets shown in QComboBox::showPopup. This is needed to make sure that the selection is properly exposed to the accessibility layer. On the accessibility layer, QAccessibleComboBox, the a11y implementation for the combobox, exposes the entries in its list child (s. QAccessibleComboBox::child) and Orca queries the selected item when the combobox gets focus, which didn't return the proper results earlier, resulting in no or the wrong entry getting announced. Extend the existing combobox a11y tests accordingly. Pick-to: 6.5 Fixes: QTBUG-117644 Change-Id: Ia26de5eafd229f7686745a2fbe03fc1eb6a713f8 Reviewed-by: Liang Qi (cherry picked from commit 5093e517b924074ab6e63658c87237be315a17e6) Reviewed-by: Qt Cherry-pick Bot --- src/widgets/widgets/qcombobox.cpp | 11 ++++++----- .../auto/other/qaccessibility/tst_qaccessibility.cpp | 8 ++++++++ 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index e8a462d3f0c..9525c09ea9c 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -2167,6 +2167,12 @@ void QComboBoxPrivate::setCurrentIndex(const QModelIndex &mi) indexBeforeChange = -1; if (indexChanged || modelResetToEmpty) { + QItemSelectionModel::SelectionFlags selectionMode = QItemSelectionModel::ClearAndSelect; + if (q->view()->selectionBehavior() == QAbstractItemView::SelectRows) + selectionMode.setFlag(QItemSelectionModel::Rows); + if (auto *model = q->view()->selectionModel()) + model->setCurrentIndex(currentIndex, selectionMode); + q->update(); emitCurrentIndexChanged(currentIndex); } @@ -2600,11 +2606,6 @@ void QComboBox::showPopup() return; #endif // Q_OS_MAC - // set current item and select it - QItemSelectionModel::SelectionFlags selectionMode = QItemSelectionModel::ClearAndSelect; - if (view()->selectionBehavior() == QAbstractItemView::SelectRows) - selectionMode.setFlag(QItemSelectionModel::Rows); - view()->selectionModel()->setCurrentIndex(d->currentIndex, selectionMode); QComboBoxPrivateContainer* container = d->viewContainer(); QRect listRect(style->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxListBoxPopup, this)); diff --git a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp index 5d8fff15ebb..455ccf3c354 100644 --- a/tests/auto/other/qaccessibility/tst_qaccessibility.cpp +++ b/tests/auto/other/qaccessibility/tst_qaccessibility.cpp @@ -3711,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")); @@ -3721,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());