5#include <QtGui/qtguiglobal.h>
6#if QT_CONFIG(accessibility)
8#include "qwindowsuiamainprovider.h"
9#include "qwindowsuiavalueprovider.h"
10#include "qwindowsuiarangevalueprovider.h"
11#include "qwindowsuiatextprovider.h"
12#include "qwindowsuiatoggleprovider.h"
13#include "qwindowsuiainvokeprovider.h"
14#include "qwindowsuiaselectionprovider.h"
15#include "qwindowsuiaselectionitemprovider.h"
16#include "qwindowsuiatableprovider.h"
17#include "qwindowsuiatableitemprovider.h"
18#include "qwindowsuiagridprovider.h"
19#include "qwindowsuiagriditemprovider.h"
20#include "qwindowsuiawindowprovider.h"
21#include "qwindowsuiaexpandcollapseprovider.h"
22#include "qwindowscontext.h"
23#include "qwindowsuiautils.h"
24#include "qwindowsuiaprovidercache.h"
26#include <QtCore/qloggingcategory.h>
27#include <QtGui/private/qaccessiblebridgeutils_p.h>
28#include <QtGui/qaccessible.h>
29#include <QtGui/qguiapplication.h>
30#include <QtGui/qwindow.h>
31#include <QtCore/private/qcomvariant_p.h>
33#if !defined(Q_CC_BOR) && !defined (Q_CC_GNU)
37#include <QtCore/qt_windows.h>
41using namespace QWindowsUiAutomation;
44ComPtr<QWindowsUiaMainProvider> QWindowsUiaMainProvider::providerForAccessible(QAccessibleInterface *accessible)
49 QAccessible::Id id = QAccessible::uniqueId(accessible);
50 QWindowsUiaProviderCache *providerCache = QWindowsUiaProviderCache::instance();
51 ComPtr<QWindowsUiaMainProvider> provider = providerCache->providerForId(id);
54 provider = makeComObject<QWindowsUiaMainProvider>(accessible);
55 providerCache->insert(id, provider.Get());
60QWindowsUiaMainProvider::QWindowsUiaMainProvider(QAccessibleInterface *a)
61 : QWindowsUiaBaseProvider(QAccessible::uniqueId(a))
65QWindowsUiaMainProvider::~QWindowsUiaMainProvider()
69void QWindowsUiaMainProvider::notifyFocusChange(QAccessibleEvent *event)
71 if (QAccessibleInterface *accessible = event->accessibleInterface()) {
73 if (accessible->childCount()) {
74 if (QAccessibleInterface *child = accessible->focusChild())
77 if (
auto provider = providerForAccessible(accessible))
78 UiaRaiseAutomationEvent(provider.Get(), UIA_AutomationFocusChangedEventId);
82void QWindowsUiaMainProvider::notifyStateChange(QAccessibleStateChangeEvent *event)
84 if (QAccessibleInterface *accessible = event->accessibleInterface()) {
85 if (event->changedStates().checked || event->changedStates().checkStateMixed) {
87 if (accessible->role() == QAccessible::CheckBox
88 || accessible->role() == QAccessible::Switch
89 || accessible->role() == QAccessible::Cell
90 || accessible->role() == QAccessible::ListItem
91 || accessible->role() == QAccessible::TreeItem) {
92 if (
auto provider = providerForAccessible(accessible)) {
93 long toggleState = ToggleState_Off;
94 if (accessible->state().checked)
95 toggleState = accessible->state().checkStateMixed ? ToggleState_Indeterminate : ToggleState_On;
98 QComVariant newVal{toggleState};
99 UiaRaiseAutomationPropertyChangedEvent(
100 provider.Get(), UIA_ToggleToggleStatePropertyId, oldVal.get(), newVal.get());
104 if (event->changedStates().expanded) {
105 if (accessible->state().expandable) {
106 if (
auto provider = providerForAccessible(accessible)) {
107 long expandedState = accessible->state().expanded ? ExpandCollapseState_Expanded : ExpandCollapseState_Collapsed;
110 QComVariant newVal{expandedState};
111 UiaRaiseAutomationPropertyChangedEvent(
112 provider.Get(), UIA_ExpandCollapseExpandCollapseStatePropertyId, oldVal.get(), newVal.get());
116 if (event->changedStates().active) {
117 if (accessible->role() == QAccessible::Window) {
119 if (
auto provider = providerForAccessible(accessible)) {
120 if (accessible->state().active) {
121 UiaRaiseAutomationEvent(provider.Get(), UIA_Window_WindowOpenedEventId);
122 if (QAccessibleInterface *focused = accessible->focusChild()) {
123 if (
auto focusedProvider = providerForAccessible(focused)) {
124 UiaRaiseAutomationEvent(focusedProvider.Get(),
125 UIA_AutomationFocusChangedEventId);
129 UiaRaiseAutomationEvent(provider.Get(), UIA_Window_WindowClosedEventId);
137void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *event)
139 if (QAccessibleInterface *accessible = event->accessibleInterface()) {
140 if (accessible->role() == QAccessible::ComboBox && accessible->childCount() > 0) {
141 QAccessibleInterface *listacc = accessible->child(0);
142 if (listacc && listacc->role() == QAccessible::List) {
143 int count = listacc->childCount();
144 for (
int i = 0; i < count; ++i) {
145 QAccessibleInterface *item = listacc->child(i);
146 if (item && item->isValid() && item->text(QAccessible::Name) == event->value()) {
147 if (!item->state().selected) {
148 if (QAccessibleActionInterface *actionInterface = item->actionInterface())
149 actionInterface->doAction(QAccessibleActionInterface::toggleAction());
156 if (event->value().typeId() == QMetaType::QString) {
157 if (
auto provider = providerForAccessible(accessible)) {
159 const QComVariant oldVal;
160 const QComVariant newVal{ event->value().toString() };
161 UiaRaiseAutomationPropertyChangedEvent(provider.Get(), UIA_ValueValuePropertyId,
162 oldVal.get(), newVal.get());
164 }
else if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
165 if (
auto provider = providerForAccessible(accessible)) {
167 const QComVariant oldVal;
168 const QComVariant newVal{ valueInterface->currentValue().toDouble() };
169 UiaRaiseAutomationPropertyChangedEvent(
170 provider.Get(), UIA_RangeValueValuePropertyId, oldVal.get(), newVal.get());
176void QWindowsUiaMainProvider::notifyNameChange(QAccessibleEvent *event)
178 if (QAccessibleInterface *accessible = event->accessibleInterface()) {
181 if (accessible->role() == QAccessible::ComboBox || accessible->state().focused) {
182 if (
auto provider = providerForAccessible(accessible)) {
184 QComVariant newVal{ accessible->text(QAccessible::Name) };
185 UiaRaiseAutomationPropertyChangedEvent(provider.Get(), UIA_NamePropertyId,
186 oldVal.get(), newVal.get());
192void QWindowsUiaMainProvider::notifyRoleChange(QAccessibleEvent *event)
194 if (QAccessibleInterface *accessible = event->accessibleInterface()) {
195 if (
auto provider = providerForAccessible(accessible)) {
197 QComVariant newVal{ roleToControlTypeId(accessible->role()) };
198 UiaRaiseAutomationPropertyChangedEvent(provider.Get(), UIA_ControlTypePropertyId,
199 oldVal.get(), newVal.get());
204void QWindowsUiaMainProvider::notifySelectionChange(QAccessibleEvent *event)
206 if (QAccessibleInterface *accessible = event->accessibleInterface()) {
207 if (
auto provider = providerForAccessible(accessible))
208 UiaRaiseAutomationEvent(provider.Get(), UIA_SelectionItem_ElementSelectedEventId);
213void QWindowsUiaMainProvider::notifyTextChange(QAccessibleEvent *event)
215 if (QAccessibleInterface *accessible = event->accessibleInterface()) {
216 if (accessible->textInterface()) {
217 if (
auto provider = providerForAccessible(accessible)) {
218 if (event->type() == QAccessible::TextSelectionChanged) {
219 UiaRaiseAutomationEvent(provider.Get(), UIA_Text_TextSelectionChangedEventId);
220 }
else if (event->type() == QAccessible::TextCaretMoved) {
221 if (!accessible->state().readOnly) {
222 UiaRaiseAutomationEvent(provider.Get(),
223 UIA_Text_TextSelectionChangedEventId);
226 UiaRaiseAutomationEvent(provider.Get(), UIA_Text_TextChangedEventId);
233void QWindowsUiaMainProvider::raiseNotification(QAccessibleAnnouncementEvent *event)
235 if (QAccessibleInterface *accessible = event->accessibleInterface()) {
236 if (
auto provider = providerForAccessible(accessible)) {
237 QBStr message{ event->message() };
238 QAccessible::AnnouncementPoliteness prio = event->politeness();
239 NotificationProcessing processing = (prio == QAccessible::AnnouncementPoliteness::Assertive)
240 ? NotificationProcessing_ImportantAll
241 : NotificationProcessing_All;
242 QBStr activityId{ QString::fromLatin1(
"") };
243#if !defined(Q_CC_MSVC) || !defined(QT_WIN_SERVER_2016_COMPAT)
244 UiaRaiseNotificationEvent(provider.Get(), NotificationKind_Other, processing, message.bstr(),
247 HMODULE uiautomationcore = GetModuleHandleW(L"UIAutomationCore.dll");
248 if (uiautomationcore != NULL) {
249 typedef HRESULT (WINAPI *EVENTFUNC)(IRawElementProviderSimple *, NotificationKind,
250 NotificationProcessing, BSTR, BSTR);
252 EVENTFUNC uiaRaiseNotificationEvent =
253 (EVENTFUNC)GetProcAddress(uiautomationcore,
"UiaRaiseNotificationEvent");
254 if (uiaRaiseNotificationEvent != NULL) {
255 uiaRaiseNotificationEvent(provider.Get(), NotificationKind_Other, processing,
256 message.bstr(), activityId.bstr());
264HRESULT STDMETHODCALLTYPE QWindowsUiaMainProvider::QueryInterface(REFIID iid, LPVOID *iface)
266 HRESULT result = QComObject::QueryInterface(iid, iface);
268 if (SUCCEEDED(result) && iid == __uuidof(IRawElementProviderFragmentRoot)) {
269 QAccessibleInterface *accessible = accessibleInterface();
270 if (accessible && hwndForAccessible(accessible)) {
274 result = E_NOINTERFACE;
282HRESULT QWindowsUiaMainProvider::get_ProviderOptions(ProviderOptions *pRetVal)
287 *pRetVal =
static_cast<ProviderOptions>(ProviderOptions_ServerSideProvider | ProviderOptions_UseComThreading);
292HRESULT QWindowsUiaMainProvider::GetPatternProvider(PATTERNID idPattern, IUnknown **pRetVal)
294 qCDebug(lcQpaUiAutomation) <<
__FUNCTION__ << idPattern;
300 QAccessibleInterface *accessible = accessibleInterface();
302 return UIA_E_ELEMENTNOTAVAILABLE;
305 case UIA_WindowPatternId:
306 if (accessible->parent() && (accessible->parent()->role() == QAccessible::Application)) {
307 *pRetVal = makeComObject<QWindowsUiaWindowProvider>(id()).Detach();
310 case UIA_TextPatternId:
311 case UIA_TextPattern2Id:
313 if (accessible->textInterface()) {
314 *pRetVal = makeComObject<QWindowsUiaTextProvider>(id()).Detach();
317 case UIA_ValuePatternId:
319 if (accessible->role() != QAccessible::StaticText)
320 *pRetVal = makeComObject<QWindowsUiaValueProvider>(id()).Detach();
322 case UIA_RangeValuePatternId:
324 if (accessible->valueInterface()) {
325 *pRetVal = makeComObject<QWindowsUiaRangeValueProvider>(id()).Detach();
328 case UIA_TogglePatternId:
330 if (accessible->state().checkable)
331 *pRetVal = makeComObject<QWindowsUiaToggleProvider>(id()).Detach();
333 case UIA_SelectionPatternId:
334 case UIA_SelectionPattern2Id:
336 if (accessible->selectionInterface()
337 || accessible->role() == QAccessible::List
338 || accessible->role() == QAccessible::PageTabList) {
339 *pRetVal = makeComObject<QWindowsUiaSelectionProvider>(id()).Detach();
342 case UIA_SelectionItemPatternId:
344 if ((accessible->parent() && accessible->parent()->selectionInterface())
345 || (accessible->role() == QAccessible::RadioButton)
346 || (accessible->role() == QAccessible::ListItem)
347 || (accessible->role() == QAccessible::PageTab)) {
348 *pRetVal = makeComObject<QWindowsUiaSelectionItemProvider>(id()).Detach();
351 case UIA_TablePatternId:
353 if (accessible->tableInterface()
354 && ((accessible->role() == QAccessible::Table) || (accessible->role() == QAccessible::Tree))) {
355 *pRetVal = makeComObject<QWindowsUiaTableProvider>(id()).Detach();
358 case UIA_TableItemPatternId:
360 if (accessible->tableCellInterface()
361 && ((accessible->role() == QAccessible::Cell) || (accessible->role() == QAccessible::TreeItem))) {
362 *pRetVal = makeComObject<QWindowsUiaTableItemProvider>(id()).Detach();
365 case UIA_GridPatternId:
367 if (accessible->tableInterface()
368 && ((accessible->role() == QAccessible::Table) || (accessible->role() == QAccessible::Tree))) {
369 *pRetVal = makeComObject<QWindowsUiaGridProvider>(id()).Detach();
372 case UIA_GridItemPatternId:
374 if (accessible->tableCellInterface()
375 && ((accessible->role() == QAccessible::Cell) || (accessible->role() == QAccessible::TreeItem))) {
376 *pRetVal = makeComObject<QWindowsUiaGridItemProvider>(id()).Detach();
379 case UIA_InvokePatternId:
381 if (accessible->actionInterface()) {
382 *pRetVal = makeComObject<QWindowsUiaInvokeProvider>(id()).Detach();
385 case UIA_ExpandCollapsePatternId:
387 if ((accessible->role() == QAccessible::MenuItem
388 && accessible->childCount() > 0
389 && accessible->child(0)->role() == QAccessible::PopupMenu)
390 || accessible->role() == QAccessible::ComboBox
391 || accessible->state().expandable) {
392 *pRetVal = makeComObject<QWindowsUiaExpandCollapseProvider>(id()).Detach();
402void QWindowsUiaMainProvider::setLabelledBy(QAccessibleInterface *accessible, VARIANT *pRetVal)
404 Q_ASSERT(accessible);
406 typedef std::pair<QAccessibleInterface*, QAccessible::Relation> RelationPair;
407 const QList<RelationPair> relationInterfaces = accessible->relations(QAccessible::Label);
408 if (relationInterfaces.empty())
412 ComPtr<IRawElementProviderSimple> provider = providerForAccessible(relationInterfaces.first().first);
416 pRetVal->vt = VT_UNKNOWN;
417 pRetVal->punkVal = provider.Detach();
420void QWindowsUiaMainProvider::fillVariantArrayForRelation(QAccessibleInterface* accessible,
421 QAccessible::Relation relation, VARIANT *pRetVal)
423 Q_ASSERT(accessible);
425 typedef std::pair<QAccessibleInterface*, QAccessible::Relation> RelationPair;
426 const QList<RelationPair> relationInterfaces = accessible->relations(relation);
427 if (relationInterfaces.empty())
430 SAFEARRAY *elements = SafeArrayCreateVector(VT_UNKNOWN, 0, relationInterfaces.size());
431 for (LONG i = 0; i < relationInterfaces.size(); ++i) {
432 if (ComPtr<IRawElementProviderSimple> provider =
433 providerForAccessible(relationInterfaces.at(i).first)) {
434 SafeArrayPutElement(elements, &i, provider.Get());
438 pRetVal->vt = VT_UNKNOWN | VT_ARRAY;
439 pRetVal->parray = elements;
442void QWindowsUiaMainProvider::setAriaProperties(QAccessibleInterface *accessible, VARIANT *pRetVal)
444 Q_ASSERT(accessible);
446 QAccessibleAttributesInterface *attributesIface = accessible->attributesInterface();
447 if (!attributesIface)
451 const QList<QAccessible::Attribute> attrKeys = attributesIface->attributeKeys();
452 for (qsizetype i = 0; i < attrKeys.size(); ++i) {
454 ariaString += QStringLiteral(
";");
455 const QAccessible::Attribute key = attrKeys.at(i);
456 const QVariant value = attributesIface->attributeValue(key);
459 case QAccessible::Attribute::Custom:
462 Q_ASSERT((value.canConvert<QHash<QString, QString>>()));
463 const QHash<QString, QString> attrMap = value.value<QHash<QString, QString>>();
464 for (
auto [name, val] : attrMap.asKeyValueRange()) {
465 if (name != *attrMap.keyBegin())
466 ariaString += QStringLiteral(
";");
467 ariaString += name + QStringLiteral(
"=") + val;
471 case QAccessible::Attribute::Level:
472 Q_ASSERT(value.canConvert<
int>());
473 ariaString += QStringLiteral(
"level=") + QString::number(value.toInt());
480 *pRetVal = QComVariant{ ariaString }.release();
483void QWindowsUiaMainProvider::setStyle(QAccessibleInterface *accessible, VARIANT *pRetVal)
485 Q_ASSERT(accessible);
487 QAccessibleAttributesInterface *attributesIface = accessible->attributesInterface();
488 if (!attributesIface)
492 if (accessible->role() != QAccessible::Role::Heading)
495 const QVariant levelVariant = attributesIface->attributeValue(QAccessible::Attribute::Level);
496 if (!levelVariant.isValid())
499 Q_ASSERT(levelVariant.canConvert<
int>());
501 const int level = levelVariant.toInt();
502 if (level < 1 || level > 9)
505 const long styleId = styleIdForHeadingLevel(level);
506 *pRetVal = QComVariant{ styleId }.release();
509int QWindowsUiaMainProvider::styleIdForHeadingLevel(
int headingLevel)
512 Q_ASSERT(headingLevel > 0 && headingLevel <= 9);
514 static constexpr int styles[] = {
526 return styles[headingLevel - 1];
529HRESULT QWindowsUiaMainProvider::GetPropertyValue(PROPERTYID idProp, VARIANT *pRetVal)
531 qCDebug(lcQpaUiAutomation) <<
__FUNCTION__ << idProp;
535 clearVariant(pRetVal);
537 QAccessibleInterface *accessible = accessibleInterface();
539 return UIA_E_ELEMENTNOTAVAILABLE;
541 bool topLevelWindow = accessible->parent() && (accessible->parent()->role() == QAccessible::Application);
544 case UIA_ProcessIdPropertyId:
546 *pRetVal = QComVariant{
static_cast<
long>(GetCurrentProcessId()) }.release();
548 case UIA_AccessKeyPropertyId:
550 *pRetVal = QComVariant{ accessible->text(QAccessible::Accelerator) }.release();
552 case UIA_AriaRolePropertyId:
553 if (accessible->role() == QAccessible::Heading)
554 *pRetVal = QComVariant{ QStringLiteral(
"heading") }.release();
556 case UIA_AriaPropertiesPropertyId:
557 setAriaProperties(accessible, pRetVal);
559 case UIA_AutomationIdPropertyId:
561 *pRetVal = QComVariant{ QAccessibleBridgeUtils::accessibleId(accessible) }.release();
563 case UIA_ClassNamePropertyId:
565 if (QObject *o = accessible->object()) {
566 QString className = QLatin1StringView(o->metaObject()->className());
567 *pRetVal = QComVariant{ className }.release();
570 case UIA_CulturePropertyId:
573 if (QAccessibleAttributesInterface *attributesIface = accessible->attributesInterface()) {
574 const QVariant localeVariant = attributesIface->attributeValue(QAccessible::Attribute::Locale);
575 if (localeVariant.isValid()) {
576 Q_ASSERT(localeVariant.canConvert<QLocale>());
577 locale = localeVariant.toLocale();
580 LCID lcid = LocaleNameToLCID(qUtf16Printable(locale.bcp47Name()), 0);
581 *pRetVal = QComVariant{
long(lcid) }.release();
584 case UIA_DescribedByPropertyId:
585 fillVariantArrayForRelation(accessible, QAccessible::DescriptionFor, pRetVal);
587 case UIA_FlowsFromPropertyId:
588 fillVariantArrayForRelation(accessible, QAccessible::FlowsTo, pRetVal);
590 case UIA_FlowsToPropertyId:
591 fillVariantArrayForRelation(accessible, QAccessible::FlowsFrom, pRetVal);
593 case UIA_LabeledByPropertyId:
594 setLabelledBy(accessible, pRetVal);
596 case UIA_FrameworkIdPropertyId:
597 *pRetVal = QComVariant{ QStringLiteral(
"Qt") }.release();
599 case UIA_ControlTypePropertyId:
600 if (topLevelWindow) {
602 *pRetVal = QComVariant{ UIA_WindowControlTypeId }.release();
605 *pRetVal = QComVariant{ roleToControlTypeId(accessible->role()) }.release();
608 case UIA_HelpTextPropertyId:
609 *pRetVal = QComVariant{ accessible->text(QAccessible::Help) }.release();
611 case UIA_HasKeyboardFocusPropertyId:
615 if (topLevelWindow) {
616 QAccessibleInterface *focusacc = accessible->focusChild();
618 *pRetVal = QComVariant{ accessible->state().active ?
true :
false }.release();
622 *pRetVal = QComVariant{ accessible->state().focused ?
true :
false }.release();
624 case UIA_IsKeyboardFocusablePropertyId:
625 if (topLevelWindow) {
627 *pRetVal = QComVariant{
true }.release();
629 *pRetVal = QComVariant{ accessible->state().focusable ?
true :
false }.release();
632 case UIA_IsOffscreenPropertyId:
633 *pRetVal = QComVariant{ accessible->state().offscreen ?
true :
false }.release();
635 case UIA_IsContentElementPropertyId:
636 *pRetVal = QComVariant{
true }.release();
638 case UIA_IsControlElementPropertyId:
639 *pRetVal = QComVariant{
true }.release();
641 case UIA_IsEnabledPropertyId:
642 *pRetVal = QComVariant{ !accessible->state().disabled }.release();
644 case UIA_IsPasswordPropertyId:
645 *pRetVal = QComVariant{ accessible->role() == QAccessible::EditableText
646 && accessible->state().passwordEdit }
649 case UIA_IsPeripheralPropertyId:
651 if (QWindow *window = windowForAccessible(accessible)) {
652 const Qt::WindowType wt = window->type();
653 *pRetVal = QComVariant{ wt == Qt::Popup || wt == Qt::ToolTip || wt == Qt::SplashScreen }
657 case UIA_IsDialogPropertyId:
658 *pRetVal = QComVariant{ accessible->role() == QAccessible::Dialog
659 || accessible->role() == QAccessible::AlertMessage }
662 case UIA_FullDescriptionPropertyId:
663 *pRetVal = QComVariant{ accessible->text(QAccessible::Description) }.release();
665 case UIA_LocalizedControlTypePropertyId:
668 if (accessible->role() == QAccessible::BlockQuote)
669 *pRetVal = QComVariant{ tr(
"blockquote") }.release();
671 case UIA_NamePropertyId: {
672 QString name = accessible->text(QAccessible::Name);
673 if (name.isEmpty() && topLevelWindow)
674 name = QCoreApplication::applicationName();
675 *pRetVal = QComVariant{ name }.release();
678 case UIA_OrientationPropertyId: {
679 OrientationType orientationType = OrientationType_None;
680 if (QAccessibleAttributesInterface *attributesIface = accessible->attributesInterface()) {
681 const QVariant orientationVariant =
682 attributesIface->attributeValue(QAccessible::Attribute::Orientation);
683 if (orientationVariant.isValid()) {
684 Q_ASSERT(orientationVariant.canConvert<Qt::Orientation>());
685 const Qt::Orientation orientation = orientationVariant.value<Qt::Orientation>();
686 orientationType = orientation == Qt::Horizontal ? OrientationType_Horizontal
687 : OrientationType_Vertical;
690 *pRetVal = QComVariant{
long(orientationType) }.release();
693 case UIA_StyleIdAttributeId:
694 setStyle(accessible, pRetVal);
702HRESULT QWindowsUiaMainProvider::get_HostRawElementProvider(IRawElementProviderSimple **pRetVal)
704 qCDebug(lcQpaUiAutomation) <<
__FUNCTION__ <<
this;
711 if (QAccessibleInterface *accessible = accessibleInterface()) {
712 if (HWND hwnd = hwndForAccessible(accessible)) {
713 return UiaHostProviderFromHwnd(hwnd, pRetVal);
720HRESULT QWindowsUiaMainProvider::Navigate(NavigateDirection direction, IRawElementProviderFragment **pRetVal)
722 qCDebug(lcQpaUiAutomation) <<
__FUNCTION__ << direction <<
" this: " <<
this;
728 QAccessibleInterface *accessible = accessibleInterface();
730 return UIA_E_ELEMENTNOTAVAILABLE;
732 QAccessibleInterface *targetacc =
nullptr;
734 if (direction == NavigateDirection_Parent) {
735 if (QAccessibleInterface *parent = accessible->parent()) {
737 if (parent->isValid() && parent->role() != QAccessible::Application) {
742 QAccessibleInterface *parent =
nullptr;
746 case NavigateDirection_FirstChild:
751 case NavigateDirection_LastChild:
753 index = accessible->childCount() - 1;
756 case NavigateDirection_NextSibling:
757 if ((parent = accessible->parent()))
758 index = parent->indexOfChild(accessible) + 1;
761 case NavigateDirection_PreviousSibling:
762 if ((parent = accessible->parent()))
763 index = parent->indexOfChild(accessible) - 1;
771 if (parent && parent->isValid()) {
772 for (
int count = parent->childCount(); index >= 0 && index < count; index += incr) {
773 if (QAccessibleInterface *child = parent->child(index)) {
774 if (child->isValid() && !child->state().invisible) {
784 *pRetVal = providerForAccessible(targetacc).Detach();
789HRESULT QWindowsUiaMainProvider::GetRuntimeId(SAFEARRAY **pRetVal)
791 qCDebug(lcQpaUiAutomation) <<
__FUNCTION__ <<
this;
797 QAccessibleInterface *accessible = accessibleInterface();
799 return UIA_E_ELEMENTNOTAVAILABLE;
803 int rtId[] = { UiaAppendRuntimeId,
int(id()) };
805 if ((*pRetVal = SafeArrayCreateVector(VT_I4, 0, 2))) {
806 for (LONG i = 0; i < 2; ++i)
807 SafeArrayPutElement(*pRetVal, &i, &rtId[i]);
813HRESULT QWindowsUiaMainProvider::get_BoundingRectangle(UiaRect *pRetVal)
815 qCDebug(lcQpaUiAutomation) <<
__FUNCTION__ <<
this;
820 QAccessibleInterface *accessible = accessibleInterface();
822 return UIA_E_ELEMENTNOTAVAILABLE;
824 QWindow *window = windowForAccessible(accessible);
826 return UIA_E_ELEMENTNOTAVAILABLE;
828 rectToNativeUiaRect(accessible->rect(), window, pRetVal);
832HRESULT QWindowsUiaMainProvider::GetEmbeddedFragmentRoots(SAFEARRAY **pRetVal)
834 qCDebug(lcQpaUiAutomation) <<
__FUNCTION__ <<
this;
844HRESULT QWindowsUiaMainProvider::SetFocus()
846 qCDebug(lcQpaUiAutomation) <<
__FUNCTION__ <<
this;
848 QAccessibleInterface *accessible = accessibleInterface();
850 return UIA_E_ELEMENTNOTAVAILABLE;
852 QAccessibleActionInterface *actionInterface = accessible->actionInterface();
853 if (!actionInterface)
854 return UIA_E_ELEMENTNOTAVAILABLE;
856 actionInterface->doAction(QAccessibleActionInterface::setFocusAction());
860HRESULT QWindowsUiaMainProvider::get_FragmentRoot(IRawElementProviderFragmentRoot **pRetVal)
862 qCDebug(lcQpaUiAutomation) <<
__FUNCTION__ <<
this;
870 if (QAccessibleInterface *accessible = accessibleInterface()) {
871 if (QWindow *window = windowForAccessible(accessible)) {
872 if (QAccessibleInterface *rootacc = window->accessibleRoot())
873 *pRetVal = providerForAccessible(rootacc).Detach();
880HRESULT QWindowsUiaMainProvider::ElementProviderFromPoint(
double x,
double y, IRawElementProviderFragment **pRetVal)
882 qCDebug(lcQpaUiAutomation) <<
__FUNCTION__ << x << y;
889 QAccessibleInterface *accessible = accessibleInterface();
891 return UIA_E_ELEMENTNOTAVAILABLE;
893 QWindow *window = windowForAccessible(accessible);
895 return UIA_E_ELEMENTNOTAVAILABLE;
898 UiaPoint uiaPoint = {x, y};
900 nativeUiaPointToPoint(uiaPoint, window, &point);
902 QAccessibleInterface *targetacc = accessible->childAt(point.x(), point.y());
905 QAccessibleInterface *acc = targetacc;
910 if (targetacc->textInterface())
break;
911 acc = acc->childAt(point.x(), point.y());
913 *pRetVal = providerForAccessible(targetacc).Detach();
919HRESULT QWindowsUiaMainProvider::GetFocus(IRawElementProviderFragment **pRetVal)
921 qCDebug(lcQpaUiAutomation) <<
__FUNCTION__ <<
this;
927 if (QAccessibleInterface *accessible = accessibleInterface()) {
928 if (QAccessibleInterface *focusacc = accessible->focusChild()) {
929 *pRetVal = providerForAccessible(focusacc).Detach();