From 8bb9a1f247362f4ebb99b048d46e2ae8daaac4ed Mon Sep 17 00:00:00 2001 From: Michael Weghorn Date: Tue, 26 Nov 2024 11:45:14 +0100 Subject: [PATCH] a11y uia: Support UIA_LabeledByPropertyId MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In the Windows accessibility bridge, bridge the QAccessible::Label relation to the corresponding UIA property, UIA_LabeledByPropertyId [1]. Unlike UIA_DescribedByPropertyId, UIA_FlowsFromPropertyId and UIA_FlowsToPropertyId which all support "VT_UNKNOWN | VT_ARRAY", i.e. returning an array of relation targets, UIA_LabeledByPropertyId only supports "VT_UNKNOWN", i.e. returning a single element. Therefore, return only the first relation target. Sample use with NVDA's Python console: 1) start the NVDA screen reader 2) run the "calendarwidget" example (examples/widgets/widgets/calendarwidget/calendarwidget.exe) 3) move focus to the "Locale" combobox 4) start NVDA's Python console (Ctrl+Insert+Z) 5) print information about the object reported via the UIA_LabeledByPropertyId property in NVDA's Python console: >>> focus.UIAElement.CurrentLabeledBy >>> focus.UIAElement.CurrentLabeledBy.CurrentName 'Locale' >>> focus.UIAElement.CurrentLabeledBy.CurrentControlType 50020 [1] https://learn.microsoft.com/en-us/windows/win32/winauto/uiauto-automation-element-propids Change-Id: Ib03bfc00356b9bdab826c4c9c3d6b2b2b9fe531f Reviewed-by: Jan Arve Sæther --- .../uiautomation/qwindowsuiamainprovider.cpp | 21 +++++++++++++++++++ .../uiautomation/qwindowsuiamainprovider.h | 1 + 2 files changed, 22 insertions(+) diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp index 89c186a2026..bfebe1d3944 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp @@ -357,6 +357,24 @@ HRESULT QWindowsUiaMainProvider::GetPatternProvider(PATTERNID idPattern, IUnknow return S_OK; } +void QWindowsUiaMainProvider::setLabelledBy(QAccessibleInterface *accessible, VARIANT *pRetVal) +{ + Q_ASSERT(accessible); + + typedef std::pair RelationPair; + const QList relationInterfaces = accessible->relations(QAccessible::Label); + if (relationInterfaces.empty()) + return; + + // UIA_LabeledByPropertyId only supports one relation + ComPtr provider = providerForAccessible(relationInterfaces.first().first); + if (!provider) + return; + + pRetVal->vt = VT_UNKNOWN; + pRetVal->punkVal = provider.Detach(); +} + void QWindowsUiaMainProvider::fillVariantArrayForRelation(QAccessibleInterface* accessible, QAccessible::Relation relation, VARIANT *pRetVal) { @@ -512,6 +530,9 @@ HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pR case UIA_FlowsToPropertyId: fillVariantArrayForRelation(accessible, QAccessible::FlowsFrom, pRetVal); break; + case UIA_LabeledByPropertyId: + setLabelledBy(accessible, pRetVal); + break; case UIA_FrameworkIdPropertyId: *pRetVal = QComVariant{ QStringLiteral("Qt") }.release(); break; diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h index 03954d28050..eae8e26901c 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h @@ -59,6 +59,7 @@ public: HRESULT STDMETHODCALLTYPE GetFocus(IRawElementProviderFragment **pRetVal) override; private: + static void setLabelledBy(QAccessibleInterface *accessible, VARIANT *pRetVal); static void fillVariantArrayForRelation(QAccessibleInterface *accessible, QAccessible::Relation relation, VARIANT *pRetVal); static void setAriaProperties(QAccessibleInterface *accessible, VARIANT *pRetVal); static void setStyle(QAccessibleInterface *accessible, VARIANT *pRetVal);