summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorVolker Hilsheimer <[email protected]>2023-05-21 14:20:05 +0200
committerQt Cherry-pick Bot <[email protected]>2023-05-22 15:09:09 +0000
commitbeb3378e08052a3820638d82ba4942f60d207045 (patch)
treeef60f15aff13fb96cc60b21618dfaeeaeba37555 /src
parent3edb8a8a10f8b46edd92fa90fb0179cbc4e9e9fa (diff)
macOS: Fix assertion in accessibility implementation for treeviews
In QAccessible's widget implementations, trees are treated as tables, with a rowCount implementation that is based on the view's current item content. That item content is the view's content, not the model's, and it changes when tree branches are expanded. The Cocoa bridge for accessibility allocates arrays of row data structures based on the rowCount implementation. Those data structures need to be invalidated and recreated when the view's content changes. To do that, emit an accessibility event for a model reset when laying out items changes the size of the view's item array. We don't know what changed during that layout process to makes this any more granular. Amends 11ae55e918082e8fdfc0c88c21049e877cc47b5b, but the problem with the data structure being stale and incorrect would have been there before that chain of changes optimizing. It didn't trigger an assert, but probably resulted in incorrect data being reported. To make trees testable, we need to actually expose them as AXOutline to the macOS accessibility framework. Until now, they have been treated like plain QWidget, e.g. AXGroup. This made them in practice in- accessible. With this change, VoiceOver works much better (although not perfeclty yet). Also remove an assert that could be triggered by an accessibility client asking for a cell for an invalid index (which can be reproduced by navigating around in a tree, following debug warnings from QAccessibleTree::indexFromLogical: invalid index). Change-Id: I7650342aa0dcd7925a94ae6a36de5a0b344c467d Reviewed-by: Qt CI Bot <[email protected]> Reviewed-by: Tor Arne Vestbø <[email protected]> (cherry picked from commit 6a4afebc5ce8db69a6c9fb398cada31e6bad5e3c) Reviewed-by: Qt Cherry-pick Bot <[email protected]>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibility.mm1
-rw-r--r--src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm4
-rw-r--r--src/widgets/itemviews/qtreeview.cpp10
3 files changed, 14 insertions, 1 deletions
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
index ab006cebc04..dc817d9d04c 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibility.mm
@@ -136,6 +136,7 @@ static void populateRoleMap()
roleMap[QAccessible::Note] = NSAccessibilityGroupRole;
roleMap[QAccessible::ComplementaryContent] = NSAccessibilityGroupRole;
roleMap[QAccessible::Graphic] = NSAccessibilityImageRole;
+ roleMap[QAccessible::Tree] = NSAccessibilityOutlineRole;
}
/*
diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
index d63c0401fde..27fd32f91f3 100644
--- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
+++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm
@@ -292,7 +292,9 @@ static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *of
QAccessibleTableInterface *table = iface->tableInterface();
Q_ASSERT(table);
QAccessibleInterface *cell = table->cellAt(m_rowIndex, m_columnIndex);
- Q_ASSERT(cell && cell->isValid());
+ if (!cell)
+ return nullptr;
+ Q_ASSERT(cell->isValid());
iface = cell;
// no longer a placeholder
diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp
index 2280cdaa2e2..d4c5d837a8b 100644
--- a/src/widgets/itemviews/qtreeview.cpp
+++ b/src/widgets/itemviews/qtreeview.cpp
@@ -3325,6 +3325,16 @@ void QTreeViewPrivate::layout(int i, bool recursiveExpanding, bool afterIsUninit
return;
}
+ // QAccessibleTree's rowCount implementation uses viewItems.size(), so
+ // we need to invalidate any cached accessibility data structures if
+ // that value changes during the run of this function.
+ const auto resetModelIfNeeded = qScopeGuard([oldViewItemsSize = viewItems.size(), this, q]{
+ if (oldViewItemsSize != viewItems.size() && QAccessible::isActive()) {
+ QAccessibleTableModelChangeEvent event(q, QAccessibleTableModelChangeEvent::ModelReset);
+ QAccessible::updateAccessibility(&event);
+ }
+ });
+
int count = 0;
if (model->hasChildren(parent)) {
if (model->canFetchMore(parent)) {