summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndre de la Rocha <andre.rocha@qt.io>2020-03-02 20:30:13 +0100
committerAndre de la Rocha <andre.rocha@qt.io>2020-03-04 13:09:48 +0100
commit566def740ec58e842e6bb37177f80e20aebaa245 (patch)
treeaa2bac7a70531a0e84e5fade27c70f4a1b41affa
parent295a16b0d3836a8f41b5133bcd9f355afb03f38b (diff)
Windows QPA: Add support to UiaRaiseNotificationEvent()
This change adds support to UiaRaiseNotificationEvent() in the UI Automation-based accessibility code, and uses it to notify changes in string-typed values, allowing Narrator, NVDA and other screen readers to notice changes in the application state that were previously missed. Fixes: QTBUG-75003 Change-Id: I646ca3a851ab7b69817d900b002eb91a3bf607a6 Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
-rw-r--r--src/platformsupport/windowsuiautomation/qwindowsuiawrapper.cpp10
-rw-r--r--src/platformsupport/windowsuiautomation/qwindowsuiawrapper_p.h3
-rw-r--r--src/platformsupport/windowsuiautomation/uiatypes_p.h16
-rw-r--r--src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp26
4 files changed, 49 insertions, 6 deletions
diff --git a/src/platformsupport/windowsuiautomation/qwindowsuiawrapper.cpp b/src/platformsupport/windowsuiautomation/qwindowsuiawrapper.cpp
index 79541fe636..8038e1a3c3 100644
--- a/src/platformsupport/windowsuiautomation/qwindowsuiawrapper.cpp
+++ b/src/platformsupport/windowsuiautomation/qwindowsuiawrapper.cpp
@@ -53,6 +53,7 @@ QWindowsUiaWrapper::QWindowsUiaWrapper()
m_pUiaHostProviderFromHwnd = reinterpret_cast<PtrUiaHostProviderFromHwnd>(uiaLib.resolve("UiaHostProviderFromHwnd"));
m_pUiaRaiseAutomationPropertyChangedEvent = reinterpret_cast<PtrUiaRaiseAutomationPropertyChangedEvent>(uiaLib.resolve("UiaRaiseAutomationPropertyChangedEvent"));
m_pUiaRaiseAutomationEvent = reinterpret_cast<PtrUiaRaiseAutomationEvent>(uiaLib.resolve("UiaRaiseAutomationEvent"));
+ m_pUiaRaiseNotificationEvent = reinterpret_cast<PtrUiaRaiseNotificationEvent>(uiaLib.resolve("UiaRaiseNotificationEvent"));
m_pUiaClientsAreListening = reinterpret_cast<PtrUiaClientsAreListening>(uiaLib.resolve("UiaClientsAreListening"));
}
}
@@ -68,7 +69,7 @@ QWindowsUiaWrapper *QWindowsUiaWrapper::instance()
return &wrapper;
}
-// True if all symbols resolved.
+// True if most symbols resolved (UiaRaiseNotificationEvent is optional).
BOOL QWindowsUiaWrapper::ready()
{
return m_pUiaReturnRawElementProvider
@@ -113,5 +114,12 @@ HRESULT QWindowsUiaWrapper::raiseAutomationEvent(IRawElementProviderSimple *pPro
return m_pUiaRaiseAutomationEvent(pProvider, id);
}
+HRESULT QWindowsUiaWrapper::raiseNotificationEvent(IRawElementProviderSimple *provider, NotificationKind notificationKind, NotificationProcessing notificationProcessing, BSTR displayString, BSTR activityId)
+{
+ if (!m_pUiaRaiseNotificationEvent)
+ return UIA_E_NOTSUPPORTED;
+ return m_pUiaRaiseNotificationEvent(provider, notificationKind, notificationProcessing, displayString, activityId);
+}
+
QT_END_NAMESPACE
diff --git a/src/platformsupport/windowsuiautomation/qwindowsuiawrapper_p.h b/src/platformsupport/windowsuiautomation/qwindowsuiawrapper_p.h
index 3ebc3008d3..9208acbc31 100644
--- a/src/platformsupport/windowsuiautomation/qwindowsuiawrapper_p.h
+++ b/src/platformsupport/windowsuiautomation/qwindowsuiawrapper_p.h
@@ -80,17 +80,20 @@ public:
HRESULT hostProviderFromHwnd(HWND hwnd, IRawElementProviderSimple **ppProvider);
HRESULT raiseAutomationPropertyChangedEvent(IRawElementProviderSimple *pProvider, PROPERTYID id, VARIANT oldValue, VARIANT newValue);
HRESULT raiseAutomationEvent(IRawElementProviderSimple *pProvider, EVENTID id);
+ HRESULT raiseNotificationEvent(IRawElementProviderSimple *provider, NotificationKind notificationKind, NotificationProcessing notificationProcessing, BSTR displayString, BSTR activityId);
private:
typedef LRESULT (WINAPI *PtrUiaReturnRawElementProvider)(HWND, WPARAM, LPARAM, IRawElementProviderSimple *);
typedef HRESULT (WINAPI *PtrUiaHostProviderFromHwnd)(HWND, IRawElementProviderSimple **);
typedef HRESULT (WINAPI *PtrUiaRaiseAutomationPropertyChangedEvent)(IRawElementProviderSimple *, PROPERTYID, VARIANT, VARIANT);
typedef HRESULT (WINAPI *PtrUiaRaiseAutomationEvent)(IRawElementProviderSimple *, EVENTID);
+ typedef HRESULT (WINAPI *PtrUiaRaiseNotificationEvent)(IRawElementProviderSimple *, NotificationKind, NotificationProcessing, BSTR, BSTR);
typedef BOOL (WINAPI *PtrUiaClientsAreListening)();
PtrUiaReturnRawElementProvider m_pUiaReturnRawElementProvider = nullptr;
PtrUiaHostProviderFromHwnd m_pUiaHostProviderFromHwnd = nullptr;
PtrUiaRaiseAutomationPropertyChangedEvent m_pUiaRaiseAutomationPropertyChangedEvent = nullptr;
PtrUiaRaiseAutomationEvent m_pUiaRaiseAutomationEvent = nullptr;
+ PtrUiaRaiseNotificationEvent m_pUiaRaiseNotificationEvent = nullptr;
PtrUiaClientsAreListening m_pUiaClientsAreListening = nullptr;
};
diff --git a/src/platformsupport/windowsuiautomation/uiatypes_p.h b/src/platformsupport/windowsuiautomation/uiatypes_p.h
index afbc957094..0d2e1161e4 100644
--- a/src/platformsupport/windowsuiautomation/uiatypes_p.h
+++ b/src/platformsupport/windowsuiautomation/uiatypes_p.h
@@ -162,6 +162,22 @@ enum ExpandCollapseState {
ExpandCollapseState_LeafNode = 3
};
+enum NotificationKind {
+ NotificationKind_ItemAdded = 0,
+ NotificationKind_ItemRemoved = 1,
+ NotificationKind_ActionCompleted = 2,
+ NotificationKind_ActionAborted = 3,
+ NotificationKind_Other = 4
+};
+
+enum NotificationProcessing {
+ NotificationProcessing_ImportantAll = 0,
+ NotificationProcessing_ImportantMostRecent = 1,
+ NotificationProcessing_All = 2,
+ NotificationProcessing_MostRecent = 3,
+ NotificationProcessing_CurrentThenMostRecent = 4
+};
+
struct UiaRect {
double left;
double top;
diff --git a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
index 9adc5c78dd..59360616a1 100644
--- a/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
+++ b/src/plugins/platforms/windows/uiautomation/qwindowsuiamainprovider.cpp
@@ -166,11 +166,27 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve
}
if (event->value().type() == QVariant::String) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
- // Notifies changes in string values.
- VARIANT oldVal, newVal;
- clearVariant(&oldVal);
- setVariantString(event->value().toString(), &newVal);
- QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal);
+
+ // Tries to notify the change using UiaRaiseNotificationEvent(), which is only available on
+ // Windows 10 version 1709 or newer. Otherwise uses UiaRaiseAutomationPropertyChangedEvent().
+
+ BSTR displayString = bStrFromQString(event->value().toString());
+ BSTR activityId = bStrFromQString(QString());
+
+ HRESULT hr = QWindowsUiaWrapper::instance()->raiseNotificationEvent(provider, NotificationKind_Other,
+ NotificationProcessing_ImportantMostRecent,
+ displayString, activityId);
+
+ ::SysFreeString(displayString);
+ ::SysFreeString(activityId);
+
+ if (hr == static_cast<HRESULT>(UIA_E_NOTSUPPORTED)) {
+ VARIANT oldVal, newVal;
+ clearVariant(&oldVal);
+ setVariantString(event->value().toString(), &newVal);
+ QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal);
+ ::SysFreeString(newVal.bstrVal);
+ }
}
} else if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {