4#include <QtGui/qtguiglobal.h>
5#if QT_CONFIG(accessibility)
26#include <QtCore/qloggingcategory.h>
27#include <QtGui/qaccessible.h>
28#include <QtGui/qguiapplication.h>
29#include <QtGui/qwindow.h>
31#if !defined(Q_CC_BOR) && !defined (Q_CC_GNU)
35#include <QtCore/qt_windows.h>
39using namespace QWindowsUiAutomation;
41QMutex QWindowsUiaMainProvider::m_mutex;
44QWindowsUiaMainProvider *QWindowsUiaMainProvider::providerForAccessible(QAccessibleInterface *accessible)
51 QAccessible::Id
id = QAccessible::uniqueId(accessible);
52 QWindowsUiaProviderCache *providerCache = QWindowsUiaProviderCache::instance();
53 auto *provider = qobject_cast<QWindowsUiaMainProvider *>(providerCache->providerForId(
id));
58 provider =
new QWindowsUiaMainProvider(accessible);
59 providerCache->insert(
id, provider);
64QWindowsUiaMainProvider::QWindowsUiaMainProvider(QAccessibleInterface *
a,
int initialRefCount)
66 m_ref(initialRefCount)
70QWindowsUiaMainProvider::~QWindowsUiaMainProvider()
74void QWindowsUiaMainProvider::notifyFocusChange(QAccessibleEvent *
event)
76 if (QAccessibleInterface *accessible =
event->accessibleInterface()) {
78 if (accessible->childCount()) {
79 if (QAccessibleInterface *
child = accessible->focusChild())
82 if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible))
87void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *
event)
89 if (QAccessibleInterface *accessible =
event->accessibleInterface()) {
90 if (
event->changedStates().checked ||
event->changedStates().checkStateMixed) {
92 if (accessible->role() == QAccessible::CheckBox) {
93 if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
94 VARIANT oldVal, newVal;
95 clearVariant(&oldVal);
97 if (accessible->state().checked)
99 setVariantI4(toggleState, &newVal);
104 if (
event->changedStates().active) {
105 if (accessible->role() == QAccessible::Window) {
107 if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
108 if (accessible->state().active) {
110 if (QAccessibleInterface *focused = accessible->focusChild()) {
111 if (QWindowsUiaMainProvider *focusedProvider = providerForAccessible(focused))
123void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *
event)
125 if (QAccessibleInterface *accessible =
event->accessibleInterface()) {
126 if (accessible->role() == QAccessible::ComboBox && accessible->childCount() > 0) {
127 QAccessibleInterface *listacc = accessible->child(0);
128 if (listacc && listacc->role() == QAccessible::List) {
129 int count = listacc->childCount();
131 QAccessibleInterface *
item = listacc->child(
i);
132 if (
item &&
item->isValid() &&
item->text(QAccessible::Name) ==
event->value()) {
133 if (!
item->state().selected) {
134 if (QAccessibleActionInterface *actionInterface =
item->actionInterface())
135 actionInterface->doAction(QAccessibleActionInterface::toggleAction());
142 if (
event->value().typeId() == QMetaType::QString) {
143 if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
148 BSTR displayString = bStrFromQString(
event->value().toString());
149 BSTR activityId = bStrFromQString(
QString());
153 displayString, activityId);
155 ::SysFreeString(displayString);
156 ::SysFreeString(activityId);
159 VARIANT oldVal, newVal;
160 clearVariant(&oldVal);
161 setVariantString(
event->value().toString(), &newVal);
163 ::SysFreeString(newVal.bstrVal);
166 }
else if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
167 if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
169 VARIANT oldVal, newVal;
170 clearVariant(&oldVal);
171 setVariantDouble(valueInterface->currentValue().toDouble(), &newVal);
178void QWindowsUiaMainProvider::notifyNameChange(QAccessibleEvent *
event)
180 if (QAccessibleInterface *accessible =
event->accessibleInterface()) {
183 if (accessible->role() == QAccessible::ComboBox) {
184 if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
185 VARIANT oldVal, newVal;
186 clearVariant(&oldVal);
187 setVariantString(accessible->text(QAccessible::Name), &newVal);
189 ::SysFreeString(newVal.bstrVal);
195void QWindowsUiaMainProvider::notifySelectionChange(QAccessibleEvent *
event)
197 if (QAccessibleInterface *accessible =
event->accessibleInterface()) {
198 if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
205void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *
event)
207 if (QAccessibleInterface *accessible =
event->accessibleInterface()) {
208 if (accessible->textInterface()) {
209 if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
210 if (
event->type() == QAccessible::TextSelectionChanged) {
212 }
else if (
event->type() == QAccessible::TextCaretMoved) {
213 if (!accessible->state().readOnly) {
224HRESULT STDMETHODCALLTYPE QWindowsUiaMainProvider::QueryInterface(REFIID iid, LPVOID *iface)
230 QAccessibleInterface *accessible = accessibleInterface();
232 const bool result = qWindowsComQueryUnknownInterfaceMulti<IRawElementProviderSimple>(
this, iid, iface)
233 || qWindowsComQueryInterface<IRawElementProviderSimple>(
this, iid, iface)
234 || qWindowsComQueryInterface<IRawElementProviderFragment>(
this, iid, iface)
235 || (accessible && hwndForAccessible(accessible) && qWindowsComQueryInterface<IRawElementProviderFragmentRoot>(
this, iid, iface));
236 return result ? S_OK : E_NOINTERFACE;
239ULONG QWindowsUiaMainProvider::AddRef()
244ULONG STDMETHODCALLTYPE QWindowsUiaMainProvider::Release()
267 qCDebug(lcQpaUiAutomation) << __FUNCTION__ << idPattern;
273 QAccessibleInterface *accessible = accessibleInterface();
279 if (accessible->parent() && (accessible->parent()->role() == QAccessible::Application)) {
280 *
pRetVal =
new QWindowsUiaWindowProvider(
id());
286 if (accessible->textInterface()) {
287 *
pRetVal =
new QWindowsUiaTextProvider(
id());
292 if (accessible->role() != QAccessible::StaticText)
293 *
pRetVal =
new QWindowsUiaValueProvider(
id());
297 if (accessible->valueInterface()) {
298 *
pRetVal =
new QWindowsUiaRangeValueProvider(
id());
303 if (accessible->state().checkable)
304 *
pRetVal =
new QWindowsUiaToggleProvider(
id());
308 if (accessible->role() == QAccessible::List
309 || accessible->role() == QAccessible::PageTabList) {
310 *
pRetVal =
new QWindowsUiaSelectionProvider(
id());
315 if ((accessible->role() == QAccessible::RadioButton)
316 || (accessible->role() == QAccessible::ListItem)
317 || (accessible->role() == QAccessible::PageTab)) {
318 *
pRetVal =
new QWindowsUiaSelectionItemProvider(
id());
323 if (accessible->tableInterface()
324 && ((accessible->role() == QAccessible::Table) || (accessible->role() == QAccessible::Tree))) {
325 *
pRetVal =
new QWindowsUiaTableProvider(
id());
330 if (accessible->tableCellInterface()
331 && ((accessible->role() == QAccessible::Cell) || (accessible->role() == QAccessible::TreeItem))) {
332 *
pRetVal =
new QWindowsUiaTableItemProvider(
id());
337 if (accessible->tableInterface()
338 && ((accessible->role() == QAccessible::Table) || (accessible->role() == QAccessible::Tree))) {
339 *
pRetVal =
new QWindowsUiaGridProvider(
id());
344 if (accessible->tableCellInterface()
345 && ((accessible->role() == QAccessible::Cell) || (accessible->role() == QAccessible::TreeItem))) {
346 *
pRetVal =
new QWindowsUiaGridItemProvider(
id());
351 if (accessible->actionInterface()) {
352 *
pRetVal =
new QWindowsUiaInvokeProvider(
id());
357 if ((accessible->role() == QAccessible::MenuItem
358 && accessible->childCount() > 0
359 && accessible->child(0)->role() == QAccessible::PopupMenu)
360 || accessible->role() == QAccessible::ComboBox
361 || (accessible->role() == QAccessible::TreeItem && accessible->state().expandable)) {
362 *
pRetVal =
new QWindowsUiaExpandCollapseProvider(
id());
374 qCDebug(lcQpaUiAutomation) << __FUNCTION__ << idProp;
380 QAccessibleInterface *accessible = accessibleInterface();
384 bool topLevelWindow = accessible->parent() && (accessible->parent()->role() == QAccessible::Application);
389 setVariantI4(
int(GetCurrentProcessId()),
pRetVal);
393 setVariantString(accessible->text(QAccessible::Accelerator),
pRetVal);
397 setVariantString(automationIdForAccessible(accessible),
pRetVal);
401 if (
QObject *
o = accessible->object()) {
410 if (topLevelWindow) {
415 auto controlType = roleToControlTypeId(accessible->role());
427 setVariantI4(controlType,
pRetVal);
431 setVariantString(accessible->text(QAccessible::Help),
pRetVal);
434 if (topLevelWindow) {
436 setVariantBool(accessible->state().active,
pRetVal);
438 setVariantBool(accessible->state().focused,
pRetVal);
442 if (topLevelWindow) {
446 setVariantBool(accessible->state().focusable,
pRetVal);
450 setVariantBool(accessible->state().offscreen,
pRetVal);
459 setVariantBool(!accessible->state().disabled,
pRetVal);
462 setVariantBool(accessible->role() == QAccessible::EditableText
463 && accessible->state().passwordEdit,
pRetVal);
473 setVariantBool(accessible->role() == QAccessible::Dialog
474 || accessible->role() == QAccessible::AlertMessage,
pRetVal);
477 setVariantString(accessible->text(QAccessible::Description),
pRetVal);
480 QString name = accessible->text(QAccessible::Name);
481 if (
name.isEmpty() && topLevelWindow)
493QString QWindowsUiaMainProvider::automationIdForAccessible(
const QAccessibleInterface *accessible)
511HRESULT QWindowsUiaMainProvider::get_HostRawElementProvider(IRawElementProviderSimple **
pRetVal)
513 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
this;
520 if (QAccessibleInterface *accessible = accessibleInterface()) {
521 if (HWND hwnd = hwndForAccessible(accessible)) {
531 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
direction <<
" this: " <<
this;
537 QAccessibleInterface *accessible = accessibleInterface();
541 QAccessibleInterface *targetacc =
nullptr;
544 if (QAccessibleInterface *
parent = accessible->parent()) {
546 if (
parent->isValid() &&
parent->role() != QAccessible::Application) {
551 QAccessibleInterface *
parent =
nullptr;
562 index = accessible->childCount() - 1;
566 if ((
parent = accessible->parent()))
571 if ((
parent = accessible->parent()))
583 if (
child->isValid() && !
child->state().invisible) {
593 *
pRetVal = providerForAccessible(targetacc);
600 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
this;
606 QAccessibleInterface *accessible = accessibleInterface();
614 if ((*
pRetVal = SafeArrayCreateVector(VT_I4, 0, 2))) {
615 for (LONG
i = 0;
i < 2; ++
i)
616 SafeArrayPutElement(*
pRetVal, &
i, &rtId[
i]);
624 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
this;
629 QAccessibleInterface *accessible = accessibleInterface();
641HRESULT QWindowsUiaMainProvider::GetEmbeddedFragmentRoots(SAFEARRAY **
pRetVal)
643 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
this;
653HRESULT QWindowsUiaMainProvider::SetFocus()
655 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
this;
657 QAccessibleInterface *accessible = accessibleInterface();
661 QAccessibleActionInterface *actionInterface = accessible->actionInterface();
662 if (!actionInterface)
665 actionInterface->doAction(QAccessibleActionInterface::setFocusAction());
671 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
this;
679 if (QAccessibleInterface *accessible = accessibleInterface()) {
681 if (QAccessibleInterface *rootacc =
window->accessibleRoot()) {
682 *
pRetVal = providerForAccessible(rootacc);
692 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
x <<
y;
699 QAccessibleInterface *accessible = accessibleInterface();
710 nativeUiaPointToPoint(uiaPoint,
window, &point);
712 QAccessibleInterface *targetacc = accessible->childAt(point.
x(), point.
y());
715 QAccessibleInterface *acc = targetacc;
720 if (targetacc->textInterface())
break;
721 acc = acc->childAt(point.
x(), point.
y());
723 *
pRetVal = providerForAccessible(targetacc);
731 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
this;
737 if (QAccessibleInterface *accessible = accessibleInterface()) {
738 if (QAccessibleInterface *focusacc = accessible->focusChild()) {
739 *
pRetVal = providerForAccessible(focusacc);
The QAccessible class provides enums and static functions related to accessibility.
static bool testAttribute(Qt::ApplicationAttribute attribute)
Returns true if attribute attribute is set; otherwise returns false.
QString applicationName
the name of this application
\inmodule QtCore\reentrant
constexpr int x() const noexcept
Returns the x coordinate of this point.
constexpr int y() const noexcept
Returns the y coordinate of this point.
\macro QT_RESTRICTED_CAST_FROM_ASCII
HRESULT raiseNotificationEvent(IRawElementProviderSimple *provider, NotificationKind notificationKind, NotificationProcessing notificationProcessing, BSTR displayString, BSTR activityId)
HRESULT raiseAutomationEvent(IRawElementProviderSimple *pProvider, EVENTID id)
static QWindowsUiaWrapper * instance()
HRESULT raiseAutomationPropertyChangedEvent(IRawElementProviderSimple *pProvider, PROPERTYID id, VARIANT oldValue, VARIANT newValue)
HRESULT hostProviderFromHwnd(HWND hwnd, IRawElementProviderSimple **ppProvider)
Combined button and popup list for selecting options.
constexpr QBindableInterface iface
@ AA_DisableNativeVirtualKeyboard
#define qCDebug(category,...)
GLint GLint GLint GLint GLint x
[0]
GLboolean GLboolean GLboolean GLboolean a
[7]
GLenum GLenum GLsizei count
#define QStringLiteral(str)
Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) noexcept
const char className[16]
[1]
IUIAutomationTreeWalker __RPC__deref_out_opt IUIAutomationElement ** parent
#define UIA_EditControlTypeId
#define UIA_WindowControlTypeId
#define UIA_TextControlTypeId
#define UIA_E_ELEMENTNOTAVAILABLE
#define UIA_E_NOTSUPPORTED
#define UIA_Window_WindowClosedEventId
#define UIA_Text_TextSelectionChangedEventId
#define UIA_SelectionItem_ElementSelectedEventId
#define UIA_Window_WindowOpenedEventId
#define UIA_AutomationFocusChangedEventId
#define UIA_Text_TextChangedEventId
#define UiaAppendRuntimeId
#define UIA_InvokePatternId
#define UIA_ValuePatternId
#define UIA_TextPattern2Id
#define UIA_GridItemPatternId
#define UIA_GridPatternId
#define UIA_TextPatternId
#define UIA_SelectionPatternId
#define UIA_ExpandCollapsePatternId
#define UIA_TableItemPatternId
#define UIA_TogglePatternId
#define UIA_TablePatternId
#define UIA_WindowPatternId
#define UIA_RangeValuePatternId
#define UIA_SelectionItemPatternId
#define UIA_AutomationIdPropertyId
#define UIA_HasKeyboardFocusPropertyId
#define UIA_AccessKeyPropertyId
#define UIA_IsControlElementPropertyId
#define UIA_IsEnabledPropertyId
#define UIA_ProcessIdPropertyId
#define UIA_IsPeripheralPropertyId
#define UIA_ClassNamePropertyId
#define UIA_HelpTextPropertyId
#define UIA_IsContentElementPropertyId
#define UIA_ValueValuePropertyId
#define UIA_RangeValueValuePropertyId
#define UIA_ControlTypePropertyId
#define UIA_ToggleToggleStatePropertyId
#define UIA_IsOffscreenPropertyId
#define UIA_IsDialogPropertyId
#define UIA_NamePropertyId
#define UIA_FrameworkIdPropertyId
#define UIA_FullDescriptionPropertyId
#define UIA_IsKeyboardFocusablePropertyId
#define UIA_IsPasswordPropertyId
interface IRawElementProviderFragment IRawElementProviderFragment
interface IRawElementProviderFragmentRoot IRawElementProviderFragmentRoot
IRawElementProviderFragment __RPC__deref_out_opt IRawElementProviderFragment ** pRetVal
@ NotificationProcessing_ImportantMostRecent
@ ProviderOptions_ServerSideProvider
@ ProviderOptions_UseComThreading
@ NavigateDirection_NextSibling
@ NavigateDirection_PreviousSibling
@ NavigateDirection_Parent
@ NavigateDirection_LastChild
@ NavigateDirection_FirstChild
@ ToggleState_Indeterminate