Qt
Internal/Contributor docs for the Qt SDK. Note: These are NOT official API docs; those are found at https://doc.qt.io/
Loading...
Searching...
No Matches
qwindowsuiaselectionprovider.cpp
Go to the documentation of this file.
1// Copyright (C) 2017 The Qt Company Ltd.
2// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
3// Qt-Security score:significant reason:default
4
5#include <QtGui/qtguiglobal.h>
6#if QT_CONFIG(accessibility)
7
8#include "qwindowsuiaselectionprovider.h"
9#include "qwindowsuiamainprovider.h"
10#include "qwindowsuiautils.h"
11#include "qwindowscontext.h"
12
13#include <QtGui/qaccessible.h>
14#include <QtCore/qloggingcategory.h>
15#include <QtCore/qstring.h>
16#include <QtCore/qlist.h>
17
18QT_BEGIN_NAMESPACE
19
20using namespace QWindowsUiAutomation;
21
22
23QWindowsUiaSelectionProvider::QWindowsUiaSelectionProvider(QAccessible::Id id) :
24 QWindowsUiaBaseProvider(id)
25{
26}
27
28QWindowsUiaSelectionProvider::~QWindowsUiaSelectionProvider()
29{
30}
31
32// Returns an array of providers with the selected items.
33HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::GetSelection(SAFEARRAY **pRetVal)
34{
35 qCDebug(lcQpaUiAutomation) << __FUNCTION__;
36
37 if (!pRetVal)
38 return E_INVALIDARG;
39 *pRetVal = nullptr;
40
41 QAccessibleInterface *accessible = accessibleInterface();
42 if (!accessible)
43 return UIA_E_ELEMENTNOTAVAILABLE;
44
45 // First get/create list of selected items, then build a safe array with the right size.
46 QList<QAccessibleInterface *> selectedList;
47 if (QAccessibleSelectionInterface *selectionInterface = accessible->selectionInterface()) {
48 selectedList = selectionInterface->selectedItems();
49 } else {
50 const int childCount = accessible->childCount();
51 selectedList.reserve(childCount);
52 for (int i = 0; i < childCount; ++i) {
53 if (QAccessibleInterface *child = accessible->child(i)) {
54 if (accessible->role() == QAccessible::PageTabList) {
55 if (child->role() == QAccessible::PageTab && child->state().focused) {
56 selectedList.append(child);
57 }
58 } else {
59 if (child->state().selected) {
60 selectedList.append(child);
61 }
62 }
63 }
64 }
65 }
66
67 if ((*pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, selectedList.size()))) {
68 for (LONG i = 0; i < selectedList.size(); ++i) {
69 if (ComPtr<IRawElementProviderSimple> provider =
70 QWindowsUiaMainProvider::providerForAccessible(selectedList.at(i))) {
71 SafeArrayPutElement(*pRetVal, &i, provider.Get());
72 }
73 }
74 }
75 return S_OK;
76}
77
78HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_CanSelectMultiple(BOOL *pRetVal)
79{
80 qCDebug(lcQpaUiAutomation) << __FUNCTION__;
81
82 if (!pRetVal)
83 return E_INVALIDARG;
84 *pRetVal = FALSE;
85
86 QAccessibleInterface *accessible = accessibleInterface();
87 if (!accessible)
88 return UIA_E_ELEMENTNOTAVAILABLE;
89
90 *pRetVal = accessible->state().multiSelectable;
91 return S_OK;
92}
93
94HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_IsSelectionRequired(BOOL *pRetVal)
95{
96 qCDebug(lcQpaUiAutomation) << __FUNCTION__;
97
98 if (!pRetVal)
99 return E_INVALIDARG;
100 *pRetVal = FALSE;
101
102 QAccessibleInterface *accessible = accessibleInterface();
103 if (!accessible)
104 return UIA_E_ELEMENTNOTAVAILABLE;
105
106 if (accessible->role() == QAccessible::PageTabList) {
107 *pRetVal = TRUE;
108 } else {
109
110 // Initially returns false if none are selected. After the first selection, it may be required.
111 bool anySelected = false;
112 if (QAccessibleSelectionInterface *selectionInterface = accessible->selectionInterface()) {
113 anySelected = selectionInterface->selectedItem(0) != nullptr;
114 } else {
115 for (int i = 0; i < accessible->childCount(); ++i) {
116 if (QAccessibleInterface *child = accessible->child(i)) {
117 if (child->state().selected) {
118 anySelected = true;
119 break;
120 }
121 }
122 }
123 }
124
125 *pRetVal = anySelected && !accessible->state().multiSelectable && !accessible->state().extSelectable;
126 }
127 return S_OK;
128}
129
130HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_FirstSelectedItem(__RPC__deref_out_opt IRawElementProviderSimple **pRetVal)
131{
132 qCDebug(lcQpaUiAutomation) << __FUNCTION__;
133
134 if (!pRetVal)
135 return E_INVALIDARG;
136 *pRetVal = nullptr;
137
138 QAccessibleInterface *accessible = accessibleInterface();
139 if (!accessible)
140 return UIA_E_ELEMENTNOTAVAILABLE;
141
142 QAccessibleInterface *firstSelectedChild = nullptr;
143 if (QAccessibleSelectionInterface *selectionInterface = accessible->selectionInterface()) {
144 firstSelectedChild = selectionInterface->selectedItem(0);
145 if (!firstSelectedChild)
146 return UIA_E_ELEMENTNOTAVAILABLE;
147 } else {
148 int i = 0;
149 while (!firstSelectedChild && i < accessible->childCount()) {
150 if (QAccessibleInterface *child = accessible->child(i)) {
151 if (accessible->role() == QAccessible::PageTabList) {
152 if (child->role() == QAccessible::PageTab && child->state().focused)
153 firstSelectedChild = child;
154 } else if (child->state().selected) {
155 firstSelectedChild = child;
156 }
157 }
158 i++;
159 }
160 }
161
162 if (!firstSelectedChild)
163 return UIA_E_ELEMENTNOTAVAILABLE;
164
165 if (ComPtr<IRawElementProviderSimple> childProvider =
166 QWindowsUiaMainProvider::providerForAccessible(firstSelectedChild)) {
167 *pRetVal = childProvider.Detach();
168 return S_OK;
169 }
170
171 return S_FALSE;
172}
173
174HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_LastSelectedItem(__RPC__deref_out_opt IRawElementProviderSimple **pRetVal)
175{
176 qCDebug(lcQpaUiAutomation) << __FUNCTION__;
177
178 if (!pRetVal)
179 return E_INVALIDARG;
180 *pRetVal = nullptr;
181
182 QAccessibleInterface *accessible = accessibleInterface();
183 if (!accessible)
184 return UIA_E_ELEMENTNOTAVAILABLE;
185
186 QAccessibleInterface *lastSelectedChild = nullptr;
187 if (QAccessibleSelectionInterface *selectionInterface = accessible->selectionInterface()) {
188 const int selectedItemCount = selectionInterface->selectedItemCount();
189 if (selectedItemCount <= 0)
190 return UIA_E_ELEMENTNOTAVAILABLE;
191 lastSelectedChild = selectionInterface->selectedItem(selectedItemCount - 1);
192 } else {
193 int i = accessible->childCount() - 1;
194 while (!lastSelectedChild && i >= 0) {
195 if (QAccessibleInterface *child = accessible->child(i)) {
196 if (accessible->role() == QAccessible::PageTabList) {
197 if (child->role() == QAccessible::PageTab && child->state().focused)
198 lastSelectedChild = child;
199 } else if (child->state().selected) {
200 lastSelectedChild = child;
201 }
202 }
203 i--;
204 }
205 }
206
207 if (!lastSelectedChild)
208 return UIA_E_ELEMENTNOTAVAILABLE;
209
210 if (ComPtr<IRawElementProviderSimple> childProvider =
211 QWindowsUiaMainProvider::providerForAccessible(lastSelectedChild)) {
212 *pRetVal = childProvider.Detach();
213 return S_OK;
214 }
215
216 return S_FALSE;
217}
218
219HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_CurrentSelectedItem(__RPC__deref_out_opt IRawElementProviderSimple **pRetVal)
220{
221 qCDebug(lcQpaUiAutomation) << __FUNCTION__;
222 return get_FirstSelectedItem(pRetVal);
223}
224
225HRESULT STDMETHODCALLTYPE QWindowsUiaSelectionProvider::get_ItemCount(__RPC__out int *pRetVal)
226{
227 qCDebug(lcQpaUiAutomation) << __FUNCTION__;
228
229 if (!pRetVal)
230 return E_INVALIDARG;
231 *pRetVal = -1;
232
233 QAccessibleInterface *accessible = accessibleInterface();
234 if (!accessible)
235 return UIA_E_ELEMENTNOTAVAILABLE;
236
237
238 if (QAccessibleSelectionInterface *selectionInterface = accessible->selectionInterface())
239 *pRetVal = selectionInterface->selectedItemCount();
240 else {
241 int selectedCount = 0;
242 for (int i = 0; i < accessible->childCount(); i++) {
243 if (QAccessibleInterface *child = accessible->child(i)) {
244 if (accessible->role() == QAccessible::PageTabList) {
245 if (child->role() == QAccessible::PageTab && child->state().focused)
246 selectedCount++;
247 } else if (child->state().selected) {
248 selectedCount++;
249 }
250 }
251 }
252 *pRetVal = selectedCount;
253 }
254
255 return S_OK;
256}
257
258QT_END_NAMESPACE
259
260#endif // QT_CONFIG(accessibility)