Details
-
Bug
-
Resolution: Done
-
P3: Somewhat important
-
5.11.1
-
None
-
macOS with VoiceOver
-
-
64e8e69d25e08ad81cdb5fb8c2897bc3c0283c9f (qt/qtbase/5.12)
Description
Repro steps: create an empty window that uses Loader { } to load a few controls (NOTE: not QtQuick 2 controls because those don't use QQuickAccessibleAttached).
Run the application with VoiceOver open. After the Loader completes, all controls loaded show up as "Group" instead of their actual role, like "StaticText" or "Button". This means users don't know which controls are interactable / focuseable.
Root cause:
QCocoaAccessibilityElement caches the initial Role value and never refreshes it afterwards.
What happens:
When a QQuickItem gets constructed, it receives the default accessibleRole = QAccessible::NoRole.
Because the construction fires a QAccessibleEvent(ObjectCreated), a equivalent QCocoaAccessibleElement gets created right after construction.
Later, the QQuickAccessibleAttached properties get created and the item's accessibleRole value gets updated, but VoiceOver will keep reading the cached value in QCocoaAccessibleElement.
The constructor of QCocoaAccessibleElement looks like this:
- (id)initWithId:(QAccessible::Id)anId
{
Q_ASSERT((int)anId < 0);
self = [super init];
if (self) { axid = anId; QAccessibleInterface *iface = QAccessible::accessibleInterface(axid); Q_ASSERT(iface); role = QCocoaAccessible::macRole(iface); }
return self;
}
Note the caching of the role value.