4#include <QtGui/qtguiglobal.h>
5#if QT_CONFIG(accessibility)
12#include <QtGui/qaccessible.h>
13#include <QtCore/qloggingcategory.h>
14#include <QtCore/qstring.h>
15#include <QtCore/qvarlengtharray.h>
19using namespace QWindowsUiAutomation;
22QWindowsUiaTextRangeProvider::QWindowsUiaTextRangeProvider(QAccessible::Id
id,
int startOffset,
int endOffset) :
23 QWindowsUiaBaseProvider(
id),
24 m_startOffset(startOffset),
25 m_endOffset(endOffset)
27 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
this << startOffset << endOffset;
30QWindowsUiaTextRangeProvider::~QWindowsUiaTextRangeProvider()
32 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
this;
35HRESULT QWindowsUiaTextRangeProvider::AddToSelection()
37 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
this;
41HRESULT QWindowsUiaTextRangeProvider::Clone(ITextRangeProvider **pRetVal)
43 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
this;
48 *pRetVal =
new QWindowsUiaTextRangeProvider(
id(), m_startOffset, m_endOffset);
53HRESULT QWindowsUiaTextRangeProvider::Compare(ITextRangeProvider *
range, BOOL *pRetVal)
55 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
this;
57 if (!
range || !pRetVal)
60 auto *targetProvider =
static_cast<QWindowsUiaTextRangeProvider *
>(
range);
61 *pRetVal = ((targetProvider->m_startOffset == m_startOffset) && (targetProvider->m_endOffset == m_endOffset));
66HRESULT QWindowsUiaTextRangeProvider::CompareEndpoints(TextPatternRangeEndpoint endpoint,
67 ITextRangeProvider *targetRange,
68 TextPatternRangeEndpoint targetEndpoint,
71 qCDebug(lcQpaUiAutomation) << __FUNCTION__
72 <<
"endpoint=" << endpoint <<
"targetRange=" << targetRange
73 <<
"targetEndpoint=" << targetEndpoint <<
"this: " <<
this;
75 if (!targetRange || !pRetVal)
78 auto *targetProvider =
static_cast<QWindowsUiaTextRangeProvider *
>(targetRange);
80 int point = (endpoint == TextPatternRangeEndpoint_Start) ? m_startOffset : m_endOffset;
81 int targetPoint = (targetEndpoint == TextPatternRangeEndpoint_Start) ?
82 targetProvider->m_startOffset : targetProvider->m_endOffset;
83 *pRetVal = point - targetPoint;
88HRESULT QWindowsUiaTextRangeProvider::ExpandToEnclosingUnit(TextUnit unit)
90 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
"unit=" << unit <<
"this: " <<
this;
92 QAccessibleInterface *accessible = accessibleInterface();
94 return UIA_E_ELEMENTNOTAVAILABLE;
96 QAccessibleTextInterface *textInterface = accessible->textInterface();
98 return UIA_E_ELEMENTNOTAVAILABLE;
100 int len = textInterface->characterCount();
105 if (unit == TextUnit_Character) {
106 m_startOffset =
qBound(0, m_startOffset,
len - 1);
107 m_endOffset = m_startOffset + 1;
110 const int start = m_startOffset >= 0 && m_startOffset <
len
111 ? m_startOffset :
len - 1;
113 if (!isTextUnitSeparator(unit,
text[
t]) && ((
t == 0) || isTextUnitSeparator(unit,
text[
t - 1]))) {
118 for (
int t = m_startOffset;
t <
len; ++
t) {
119 if ((
t ==
len - 1) || (isTextUnitSeparator(unit,
text[
t]) && ((unit == TextUnit_Word) || !isTextUnitSeparator(unit,
text[
t + 1])))) {
130HRESULT QWindowsUiaTextRangeProvider::FindAttribute(TEXTATTRIBUTEID ,
132 ITextRangeProvider **pRetVal)
141HRESULT STDMETHODCALLTYPE QWindowsUiaTextRangeProvider::GetAttributeValue(TEXTATTRIBUTEID attributeId,
144 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
"attributeId=" << attributeId <<
"this: " <<
this;
148 clearVariant(pRetVal);
150 QAccessibleInterface *accessible = accessibleInterface();
152 return UIA_E_ELEMENTNOTAVAILABLE;
154 QAccessibleTextInterface *textInterface = accessible->textInterface();
156 return UIA_E_ELEMENTNOTAVAILABLE;
158 switch (attributeId) {
159 case UIA_IsReadOnlyAttributeId:
160 setVariantBool(accessible->state().readOnly, pRetVal);
162 case UIA_CaretPositionAttributeId:
163 if (textInterface->cursorPosition() == 0)
164 setVariantI4(CaretPosition_BeginningOfLine, pRetVal);
165 else if (textInterface->cursorPosition() == textInterface->characterCount())
166 setVariantI4(CaretPosition_EndOfLine, pRetVal);
168 setVariantI4(CaretPosition_Unknown, pRetVal);
170 case UIA_StrikethroughStyleAttributeId:
175 const TextDecorationLineStyle uiaLineStyle = uiaLineStyleForIA2LineStyle(
value);
176 setVariantI4(uiaLineStyle, pRetVal);
186HRESULT QWindowsUiaTextRangeProvider::GetBoundingRectangles(SAFEARRAY **pRetVal)
188 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
this;
193 QAccessibleInterface *accessible = accessibleInterface();
195 return UIA_E_ELEMENTNOTAVAILABLE;
197 QAccessibleTextInterface *textInterface = accessible->textInterface();
199 return UIA_E_ELEMENTNOTAVAILABLE;
203 return UIA_E_ELEMENTNOTAVAILABLE;
205 int len = textInterface->characterCount();
206 QVarLengthArray<QRect> rectList;
208 if ((m_startOffset >= 0) && (m_endOffset <=
len) && (m_startOffset < m_endOffset)) {
210 textInterface->textAtOffset(m_startOffset, QAccessible::LineBoundary, &
start, &
end);
211 while ((
start >= 0) && (
end >= 0)) {
212 int startRange =
qMax(
start, m_startOffset);
213 int endRange =
qMin(
end, m_endOffset);
214 if (startRange < endRange) {
216 const QRect startRect = textInterface->characterRect(startRange);
217 const QRect endRect = textInterface->characterRect(endRange - 1);
218 const QRect lineRect(
qMin(startRect.x(), endRect.
x()),
219 qMin(startRect.y(), endRect.
y()),
220 qMax(startRect.x() + startRect.width(), endRect.
x() + endRect.
width()) -
qMin(startRect.x(), endRect.
x()),
221 qMax(startRect.y() + startRect.height(), endRect.
y() + endRect.
height()) -
qMin(startRect.y(), endRect.
y()));
222 rectList.append(lineRect);
225 textInterface->textAfterOffset(
end + 1, QAccessible::LineBoundary, &
start, &
end);
229 if ((*pRetVal = SafeArrayCreateVector(VT_R8, 0, 4 * rectList.size()))) {
230 for (
int i = 0;
i < rectList.size(); ++
i) {
233 rectToNativeUiaRect(rectList[
i],
window, &uiaRect);
234 double coords[4] = { uiaRect.left, uiaRect.top, uiaRect.width, uiaRect.height };
235 for (
int j = 0;
j < 4; ++
j) {
236 LONG idx = 4 *
i +
j;
237 SafeArrayPutElement(*pRetVal, &idx, &
coords[
j]);
245HRESULT QWindowsUiaTextRangeProvider::GetChildren(SAFEARRAY **pRetVal)
247 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
this;
252 *pRetVal = SafeArrayCreateVector(VT_UNKNOWN, 0, 0);
257HRESULT QWindowsUiaTextRangeProvider::GetEnclosingElement(IRawElementProviderSimple **pRetVal)
259 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
this;
264 QAccessibleInterface *accessible = accessibleInterface();
266 return UIA_E_ELEMENTNOTAVAILABLE;
268 *pRetVal = QWindowsUiaMainProvider::providerForAccessible(accessible);
275 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
maxLength <<
"this: " <<
this;
281 QAccessibleInterface *accessible = accessibleInterface();
283 return UIA_E_ELEMENTNOTAVAILABLE;
285 QAccessibleTextInterface *textInterface = accessible->textInterface();
287 return UIA_E_ELEMENTNOTAVAILABLE;
289 int len = textInterface->characterCount();
291 if ((m_startOffset >= 0) && (m_endOffset <=
len) && (m_startOffset < m_endOffset))
292 rangeText = textInterface->text(m_startOffset, m_endOffset);
296 *pRetVal = bStrFromQString(rangeText);
301HRESULT QWindowsUiaTextRangeProvider::Move(TextUnit unit,
int count,
int *pRetVal)
303 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
"unit=" << unit <<
"count=" <<
count <<
"this: " <<
this;
309 QAccessibleInterface *accessible = accessibleInterface();
311 return UIA_E_ELEMENTNOTAVAILABLE;
313 QAccessibleTextInterface *textInterface = accessible->textInterface();
315 return UIA_E_ELEMENTNOTAVAILABLE;
317 int len = textInterface->characterCount();
322 if (unit == TextUnit_Character) {
327 *pRetVal =
start - m_startOffset;
328 m_startOffset =
start;
331 MoveEndpointByUnit(TextPatternRangeEndpoint_End, unit,
count, pRetVal);
332 MoveEndpointByUnit(TextPatternRangeEndpoint_Start, unit,
count, pRetVal);
334 MoveEndpointByUnit(TextPatternRangeEndpoint_Start, unit,
count, pRetVal);
335 MoveEndpointByUnit(TextPatternRangeEndpoint_End, unit,
count, pRetVal);
342HRESULT QWindowsUiaTextRangeProvider::MoveEndpointByRange(TextPatternRangeEndpoint endpoint,
343 ITextRangeProvider *targetRange,
344 TextPatternRangeEndpoint targetEndpoint)
349 qCDebug(lcQpaUiAutomation) << __FUNCTION__
350 <<
"endpoint=" << endpoint <<
"targetRange=" << targetRange <<
"targetEndpoint=" << targetEndpoint <<
"this: " <<
this;
352 auto *targetProvider =
static_cast<QWindowsUiaTextRangeProvider *
>(targetRange);
354 int targetPoint = (targetEndpoint == TextPatternRangeEndpoint_Start) ?
355 targetProvider->m_startOffset : targetProvider->m_endOffset;
358 if (endpoint == TextPatternRangeEndpoint_Start) {
359 m_startOffset = targetPoint;
360 if (m_endOffset < m_startOffset)
361 m_endOffset = m_startOffset;
363 m_endOffset = targetPoint;
364 if (m_endOffset < m_startOffset)
365 m_startOffset = m_endOffset;
371HRESULT QWindowsUiaTextRangeProvider::MoveEndpointByUnit(TextPatternRangeEndpoint endpoint,
372 TextUnit unit,
int count,
375 qCDebug(lcQpaUiAutomation) << __FUNCTION__
376 <<
"endpoint=" << endpoint <<
"unit=" << unit <<
"count=" <<
count <<
"this: " <<
this;
382 QAccessibleInterface *accessible = accessibleInterface();
384 return UIA_E_ELEMENTNOTAVAILABLE;
386 QAccessibleTextInterface *textInterface = accessible->textInterface();
388 return UIA_E_ELEMENTNOTAVAILABLE;
390 int len = textInterface->characterCount();
395 if (unit == TextUnit_Character) {
396 if (endpoint == TextPatternRangeEndpoint_Start) {
400 m_endOffset =
qBound(m_startOffset, m_endOffset,
len);
405 m_startOffset =
qBound(0, m_startOffset, m_endOffset);
411 if (endpoint == TextPatternRangeEndpoint_Start) {
413 for (
int t = m_startOffset; (
t <
len - 1) && (moved <
count); ++
t) {
414 if (isTextUnitSeparator(unit,
text[
t]) && !isTextUnitSeparator(unit,
text[
t + 1])) {
415 m_startOffset =
t + 1;
419 m_endOffset =
qBound(m_startOffset, m_endOffset,
len);
421 const int start = m_startOffset >= 0 && m_startOffset <=
len
422 ? m_startOffset :
len;
424 if (!isTextUnitSeparator(unit,
text[
t]) && ((
t == 0) || isTextUnitSeparator(unit,
text[
t - 1]))) {
432 for (
int t = m_endOffset; (
t <
len) && (moved <
count); ++
t) {
433 if ((
t ==
len - 1) || (isTextUnitSeparator(unit,
text[
t]) && ((unit == TextUnit_Word) || !isTextUnitSeparator(unit,
text[
t + 1])))) {
440 for (
int t = m_endOffset - 2; (
t > 0) && (moved >
count); --
t) {
441 if (isTextUnitSeparator(unit,
text[
t]) && ((unit == TextUnit_Word) || !isTextUnitSeparator(unit,
text[
t + 1]))) {
447 m_startOffset =
qBound(0, m_startOffset, m_endOffset);
455HRESULT QWindowsUiaTextRangeProvider::RemoveFromSelection()
457 qCDebug(lcQpaUiAutomation) << __FUNCTION__;
463HRESULT QWindowsUiaTextRangeProvider::ScrollIntoView(BOOL alignToTop)
465 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
"alignToTop=" << alignToTop <<
"this: " <<
this;
467 QAccessibleInterface *accessible = accessibleInterface();
469 return UIA_E_ELEMENTNOTAVAILABLE;
471 QAccessibleTextInterface *textInterface = accessible->textInterface();
473 return UIA_E_ELEMENTNOTAVAILABLE;
475 textInterface->scrollToSubstring(m_startOffset, m_endOffset);
480HRESULT QWindowsUiaTextRangeProvider::Select()
482 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
this;
484 QAccessibleInterface *accessible = accessibleInterface();
486 return UIA_E_ELEMENTNOTAVAILABLE;
488 QAccessibleTextInterface *textInterface = accessible->textInterface();
490 return UIA_E_ELEMENTNOTAVAILABLE;
494 textInterface->addSelection(m_startOffset, m_endOffset);
499HRESULT QWindowsUiaTextRangeProvider::FindText(BSTR , BOOL ,
501 ITextRangeProvider **pRetVal)
510HRESULT QWindowsUiaTextRangeProvider::unselect()
512 qCDebug(lcQpaUiAutomation) << __FUNCTION__ <<
this;
514 QAccessibleInterface *accessible = accessibleInterface();
516 return UIA_E_ELEMENTNOTAVAILABLE;
518 QAccessibleTextInterface *textInterface = accessible->textInterface();
520 return UIA_E_ELEMENTNOTAVAILABLE;
522 int selCount = textInterface->selectionCount();
524 for (
int i = selCount - 1;
i >= 0; --
i)
525 textInterface->removeSelection(
i);
531QString QWindowsUiaTextRangeProvider::valueForIA2Attribute(QAccessibleTextInterface *textInterface,
538 const QString attributes = textInterface->attributes(m_startOffset, &startOffset, &endOffset);
540 if (startOffset > m_startOffset || endOffset < m_endOffset)
547 return items[1].toString();
553TextDecorationLineStyle QWindowsUiaTextRangeProvider::uiaLineStyleForIA2LineStyle(
const QString &ia2LineStyle)
556 return TextDecorationLineStyle_None;
558 return TextDecorationLineStyle_Single;
560 return TextDecorationLineStyle_Double;
562 return TextDecorationLineStyle_Other;
qsizetype count() const noexcept
\inmodule QtCore\reentrant
constexpr int height() const noexcept
Returns the height of the rectangle.
constexpr int x() const noexcept
Returns the x-coordinate of the rectangle's left edge.
constexpr int width() const noexcept
Returns the width of the rectangle.
constexpr int y() const noexcept
Returns the y-coordinate of the rectangle's top edge.
\macro QT_RESTRICTED_CAST_FROM_ASCII
Combined button and popup list for selecting options.
EGLOutputLayerEXT EGLint EGLAttrib value
[5]
#define qCDebug(category,...)
constexpr const T & qMin(const T &a, const T &b)
constexpr const T & qBound(const T &min, const T &val, const T &max)
constexpr const T & qMax(const T &a, const T &b)
GLsizei const GLubyte GLsizei GLenum const void * coords
GLenum GLenum GLsizei count
#define QStringLiteral(str)