From 3236cc3f1a87b36cb296ccafb604826645d19f86 Mon Sep 17 00:00:00 2001 From: Volker Hilsheimer Date: Fri, 8 Dec 2023 16:53:51 +0100 Subject: [PATCH] QComboBox: inform accessibility about model change before selecting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QComboBox implicitly selects the first item that gets inserted into the model. This happens in response to the model's rowInserted signal, at which point the item view might not have handled the rowInserted signal yet. Because of that, the view couldn't update the accessibility bridge, so informing accessibility about a row being selected that doens't exist in the bridge's representation of the table yet will result in data being out of sync, and depending on the bridge implementation trigger asserts. Fix this by explicitly updating the accessibility bridge before implicitly selecting the first row. Fixes: QTBUG-119526 Fixes: QTBUG-118585 Pick-to: 6.6 6.5 Change-Id: I2830c00751b3f18feb5d9252b23823c80229fed1 Reviewed-by: Tor Arne Vestbø Reviewed-by: Jan Arve Sæther --- .../platforms/cocoa/qcocoaaccessibilityelement.mm | 11 +++++++++++ src/widgets/widgets/qcombobox.cpp | 11 +++++++++++ 2 files changed, 22 insertions(+) diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index f67a66a2d36..8472506d235 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -9,12 +9,15 @@ #include "qcocoawindow.h" #include "qcocoascreen.h" +#include #include #include #include QT_USE_NAMESPACE +Q_LOGGING_CATEGORY(lcAccessibilityTable, "qt.accessibility.table") + #if QT_CONFIG(accessibility) /** @@ -131,6 +134,12 @@ - (instancetype)initWithId:(QAccessible::Id)anId role:(NSAccessibilityRole)role auto *tableElement = [QMacAccessibilityElement elementWithInterface:table]; Q_ASSERT(tableElement); Q_ASSERT(tableElement->rows); + + qCDebug(lcAccessibilityTable) << "Creating cell representation for" + << m_rowIndex << m_columnIndex + << "in table with" + << tableElement->rows.count << "rows"; + Q_ASSERT(int(tableElement->rows.count) > m_rowIndex); auto *rowElement = tableElement->rows[m_rowIndex]; if (!rowElement->columns) { @@ -273,6 +282,8 @@ - (void)updateTableModel if (QAccessibleInterface *iface = self.qtInterface) { if (QAccessibleTableInterface *table = iface->tableInterface()) { Q_ASSERT(!self.isManagedByParent); + qCDebug(lcAccessibilityTable) << "Updating table representation with" + << table->rowCount() << table->columnCount(); rows = [self populateTableArray:rows role:NSAccessibilityRowRole count:table->rowCount()]; columns = [self populateTableArray:columns role:NSAccessibilityColumnRole count:table->columnCount()]; } diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index dd41863f47d..9b10ca7e35a 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -1096,6 +1096,17 @@ void QComboBoxPrivate::_q_rowsInserted(const QModelIndex &parent, int start, int // set current index if combo was previously empty and there is no placeholderText if (start == 0 && (end - start + 1) == q->count() && !currentIndex.isValid() && placeholderText.isEmpty()) { +#if QT_CONFIG(accessibility) + // This might have been called by the model emitting rowInserted(), at which + // point the view won't have updated the accessibility bridge yet about its new + // dimensions. Do it now so that the change of the selection matches the row + // indexes of the accessibility bridge's representation. + if (container && container->itemView()) { + QAccessibleTableModelChangeEvent event(container->itemView(), + QAccessibleTableModelChangeEvent::ModelReset); + QAccessible::updateAccessibility(&event); + } +#endif q->setCurrentIndex(0); // need to emit changed if model updated index "silently" } else if (currentIndex.row() != indexBeforeChange) {