From 0377ad2f831dc782ce34369de5669f836d64763a Mon Sep 17 00:00:00 2001 From: Michael Weghorn Date: Wed, 24 Apr 2024 08:42:12 +0200 Subject: [PATCH] a11y uia: Forward new QAccessibleAnnouncementEvent to UIA Bridge the newly added QAccessibleAnnouncementEvent to UIA on Windows, by calling UiaRaiseNotificationEvent [1]. This makes the announcement from the example app attached to QTBUG-75003 work when using the NVDA screen reader on Windows. As described in commit d25d9f2c2673bc287590d9a83bd7ef1357d7021a, implement the UiaRaiseNotificationEvent function for MingW in qwindowsuiautomation as MingW doesn't provide that itself yet (see the earlier MingW build failure without that "kludge" in place: [2]). [1] https://learn.microsoft.com/en-us/windows/win32/api/uiautomationcoreapi/nf-uiautomationcoreapi-uiaraisenotificationevent [2] https://testresults.qt.io/logs/qt/qtbase/e56b201c7260ebb02ca2d030a71b9f11e40a08ac/WindowsWindows_11_23H2x86_64WindowsWindows_11_23H2x86_64Clangqtci-windows-11_23H2-x86_64-52-8f4da0Sccache_UseConfigure/a2e63edda6293b516dbe4a96615c7aa3530d3c4d/build_1714142084/log.txt.gz Fixes: QTBUG-75003 Change-Id: Ia32d49276e0dd33cff5113b4169ee317869390e7 Reviewed-by: Oliver Wolff --- .../uiautomation/qwindowsuiaaccessibility.cpp | 3 +++ .../uiautomation/qwindowsuiamainprovider.cpp | 18 ++++++++++++++++++ .../uiautomation/qwindowsuiamainprovider.h | 1 + .../uiautomation/qwindowsuiautomation.cpp | 8 ++++++++ 4 files changed, 30 insertions(+) diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp index 1abb412ccd..5892493281 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiaaccessibility.cpp @@ -127,6 +127,9 @@ void QWindowsUiaAccessibility::notifyAccessibilityUpdate(QAccessibleEvent *event return; switch (event->type()) { + case QAccessible::Announcement: + QWindowsUiaMainProvider::raiseNotification(static_cast(event)); + break; case QAccessible::Focus: QWindowsUiaMainProvider::notifyFocusChange(event); break; diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp index 95ddbcced6..b8f2d0eadd 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp @@ -204,6 +204,24 @@ void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event) } } +void QWindowsUiaMainProvider::raiseNotification(QAccessibleAnnouncementEvent *event) +{ + if (QAccessibleInterface *accessible = event->accessibleInterface()) { + if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { + BSTR message = bStrFromQString(event->message()); + QAccessible::AnnouncementPriority prio = event->priority(); + NotificationProcessing processing = (prio == QAccessible::AnnouncementPriority::Assertive) + ? NotificationProcessing_ImportantAll + : NotificationProcessing_All; + BSTR activityId = bStrFromQString(QString::fromLatin1("")); + UiaRaiseNotificationEvent(provider, NotificationKind_Other, processing, message, activityId); + + ::SysFreeString(message); + ::SysFreeString(activityId); + } + } +} + HRESULT STDMETHODCALLTYPE QWindowsUiaMainProvider::QueryInterface(REFIID iid, LPVOID *iface) { HRESULT result = QComObject::QueryInterface(iid, iface); diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h index 99db0ed318..b24f4a6cc3 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.h @@ -34,6 +34,7 @@ public: static void notifyNameChange(QAccessibleEvent *event); static void notifySelectionChange(QAccessibleEvent *event); static void notifyTextChange(QAccessibleEvent *event); + static void raiseNotification(QAccessibleAnnouncementEvent *event); // IUnknown HRESULT STDMETHODCALLTYPE QueryInterface(REFIID id, LPVOID *iface) override; diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.cpp index 1593a07202..6954a881d0 100644 --- a/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.cpp +++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiautomation.cpp @@ -69,6 +69,14 @@ HRESULT WINAPI UiaRaiseAutomationEvent(IRawElementProviderSimple *pProvider, EVE return func.invoke(pProvider, id); } +HRESULT WINAPI UiaRaiseNotificationEvent( + IRawElementProviderSimple *pProvider, NotificationKind notificationKind, + NotificationProcessing notificationProcessing, BSTR displayString, BSTR activityId) +{ + static auto func = winapi_func("uiautomationcore", FN(UiaRaiseNotificationEvent)); + return func.invoke(pProvider, notificationKind, notificationProcessing, displayString, activityId); +} + #endif // defined(__MINGW32__) || defined(__MINGW64__) #endif // QT_CONFIG(accessibility)