a11y uia: Report UIA_StrikethroughStyleAttributeId

Implement support for getting the strikethrough
style (UIA attribute UIA_StrikethroughStyleAttributeId [1])
by checking for the corresponding IAccessible2
text attribute "text-line-through-type" [2] and
mapping the value accordingly if set.

Only report those attributes from the
QAccessibleTextInterface::attributes return value,
if they apply for the whole range of the
QWindowsUiaTextRangeProvider.

With this in place, the NVDA screen reader on
Windows announces "strikethrough" as expected
when asked to report the formatting information
(e.g. via NVDA+f shortcut) for the QTBUG-118106 example.

[1] https://learn.microsoft.com/en-us/windows/win32/winauto/uiauto-textattribute-ids
[2] https://wiki.linuxfoundation.org/accessibility/iaccessible2/textattributes

Task-number: QTBUG-118106
Change-Id: I2fa060bd3bf493227bba766385f34d224497784c
Reviewed-by: Jan Arve Sæther <jan-arve.saether@qt.io>
This commit is contained in:
Michael Weghorn 2023-10-13 19:00:01 +02:00
parent d2bf45c6ed
commit f67499baab
3 changed files with 69 additions and 0 deletions

View File

@ -66,6 +66,28 @@ enum TextPatternRangeEndpoint {
TextPatternRangeEndpoint_End = 1 TextPatternRangeEndpoint_End = 1
}; };
enum TextDecorationLineStyle {
TextDecorationLineStyle_None = 0,
TextDecorationLineStyle_Single = 1,
TextDecorationLineStyle_WordsOnly = 2,
TextDecorationLineStyle_Double = 3,
TextDecorationLineStyle_Dot = 4,
TextDecorationLineStyle_Dash = 5,
TextDecorationLineStyle_DashDot = 6,
TextDecorationLineStyle_DashDotDot = 7,
TextDecorationLineStyle_Wavy = 8,
TextDecorationLineStyle_ThickSingle = 9,
TextDecorationLineStyle_DoubleWavy = 11,
TextDecorationLineStyle_ThickWavy = 12,
TextDecorationLineStyle_LongDash = 13,
TextDecorationLineStyle_ThickDash = 14,
TextDecorationLineStyle_ThickDashDot = 15,
TextDecorationLineStyle_ThickDashDotDot = 16,
TextDecorationLineStyle_ThickDot = 17,
TextDecorationLineStyle_ThickLongDash = 18,
TextDecorationLineStyle_Other = -1
};
enum CaretPosition { enum CaretPosition {
CaretPosition_Unknown = 0, CaretPosition_Unknown = 0,
CaretPosition_EndOfLine = 1, CaretPosition_EndOfLine = 1,

View File

@ -167,6 +167,15 @@ HRESULT STDMETHODCALLTYPE QWindowsUiaTextRangeProvider::GetAttributeValue(TEXTAT
else else
setVariantI4(CaretPosition_Unknown, pRetVal); setVariantI4(CaretPosition_Unknown, pRetVal);
break; break;
case UIA_StrikethroughStyleAttributeId:
{
const QString value = valueForIA2Attribute(textInterface, QStringLiteral("text-line-through-type"));
if (value.isEmpty())
break;
const TextDecorationLineStyle uiaLineStyle = uiaLineStyleForIA2LineStyle(value);
setVariantI4(uiaLineStyle, pRetVal);
break;
}
default: default:
break; break;
} }
@ -517,6 +526,42 @@ HRESULT QWindowsUiaTextRangeProvider::unselect()
return S_OK; return S_OK;
} }
// helper method to retrieve the value of the given IAccessible2 text attribute,
// or an empty string if not set
QString QWindowsUiaTextRangeProvider::valueForIA2Attribute(QAccessibleTextInterface *textInterface,
const QString &key)
{
Q_ASSERT(textInterface);
int startOffset;
int endOffset;
const QString attributes = textInterface->attributes(m_startOffset, &startOffset, &endOffset);
// don't report if attributes don't apply for the whole range
if (startOffset > m_startOffset || endOffset < m_endOffset)
return {};
for (auto attr : QStringTokenizer{attributes, u';'})
{
const QList<QStringView> items = attr.split(u':', Qt::SkipEmptyParts, Qt::CaseSensitive);
if (items.count() == 2 && items[0] == key)
return items[1].toString();
}
return {};
}
TextDecorationLineStyle QWindowsUiaTextRangeProvider::uiaLineStyleForIA2LineStyle(const QString &ia2LineStyle)
{
if (ia2LineStyle == QStringLiteral("none"))
return TextDecorationLineStyle_None;
if (ia2LineStyle == QStringLiteral("single"))
return TextDecorationLineStyle_Single;
if (ia2LineStyle == QStringLiteral("double"))
return TextDecorationLineStyle_Double;
return TextDecorationLineStyle_Other;
}
QT_END_NAMESPACE QT_END_NAMESPACE
#endif // QT_CONFIG(accessibility) #endif // QT_CONFIG(accessibility)

View File

@ -42,6 +42,8 @@ public:
private: private:
HRESULT unselect(); HRESULT unselect();
QString valueForIA2Attribute(QAccessibleTextInterface *textInterface, const QString &key);
TextDecorationLineStyle uiaLineStyleForIA2LineStyle(const QString &ia2LineStyle);
int m_startOffset; int m_startOffset;
int m_endOffset; int m_endOffset;
}; };