include/vcl/accessibility/AccessibleTextAttributeHelper.hxx | 14 ++ vcl/qt5/QtAccessibleWidget.cxx | 11 -- vcl/source/accessibility/AccessibleTextAttributeHelper.cxx | 61 ++++++++++++ 3 files changed, 77 insertions(+), 9 deletions(-)
New commits: commit ec2e02cfa41510c3d30b118cbf7595c84a046d03 Author: Michael Weghorn <m.wegh...@posteo.de> AuthorDate: Tue Oct 17 14:36:58 2023 +0200 Commit: Michael Weghorn <m.wegh...@posteo.de> CommitDate: Wed Oct 18 12:48:57 2023 +0200 tdf#157696 a11y: Report spelling error via IA2 "invalid:spelling" attr Let `AccessibleTextAttributeHelper::GetIAccessible2TextAttributes` also report spelling errors as a text attribute, since the "invalid:" text attribute with a value of "spelling" is specified for that in the IAccessible2 tex attributes specification [1]. In order to adapt the start/end index for the attribute run, iterate over all of the text markups that can be retrieved from the `XAccessibleTextMarkup` interface instead of just deterining whether the offset itself lies within a range of misspelled text via `XAccessibleTextMarkup::getTextMarkupAtIndex`. (This is strongly inspired by how the gtk3 a11y implementation does it, s. `handle_text_markup_as_run_attribute` in vcl/unx/gtk3/a11y/atktext.cxx.) When using the qt6 VCL plugin on Linux, the attribute shows up as expected in Accerciser and the Orca screen reader announces "misspelled" when moving the cursor in front of a misspelled word using the Arrow_Right key. Announcement by NVDA works once winaccessibility and NVDA have been switched over to use IAccessible2 text attributes instead of custom LibreOffice ones. [1] https://wiki.linuxfoundation.org/accessibility/iaccessible2/textattributes Change-Id: I54e5bcbb4bef4c73068243f91a3ee69c10326460 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158089 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.wegh...@posteo.de> diff --git a/vcl/source/accessibility/AccessibleTextAttributeHelper.cxx b/vcl/source/accessibility/AccessibleTextAttributeHelper.cxx index 5862b96a86c6..f69b7483d9e5 100644 --- a/vcl/source/accessibility/AccessibleTextAttributeHelper.cxx +++ b/vcl/source/accessibility/AccessibleTextAttributeHelper.cxx @@ -20,10 +20,12 @@ #include <vcl/accessibility/AccessibleTextAttributeHelper.hxx> #include <com/sun/star/accessibility/AccessibleTextType.hpp> +#include <com/sun/star/accessibility/XAccessibleTextMarkup.hpp> #include <com/sun/star/awt/FontSlant.hpp> #include <com/sun/star/awt/FontStrikeout.hpp> #include <com/sun/star/awt/FontUnderline.hpp> #include <com/sun/star/awt/FontWeight.hpp> +#include <com/sun/star/text/TextMarkupType.hpp> #include <o3tl/any.hxx> #include <tools/color.hxx> @@ -303,13 +305,53 @@ OUString AccessibleTextAttributeHelper::GetIAccessible2TextAttributes( const css::uno::Sequence<css::beans::PropertyValue> attribs = xText->getCharacterAttributes(nOffset, css::uno::Sequence<OUString>()); - const OUString sAttributes = ConvertUnoToIAccessible2TextAttributes(attribs); + OUString sAttributes = ConvertUnoToIAccessible2TextAttributes(attribs); css::accessibility::TextSegment aAttributeRun = xText->getTextAtIndex(nOffset, css::accessibility::AccessibleTextType::ATTRIBUTE_RUN); rStartOffset = aAttributeRun.SegmentStart; rEndOffset = aAttributeRun.SegmentEnd; + // report spelling error as "invalid:spelling;" IA2 text attribute and + // adapt start/end index as necessary + css::uno::Reference<css::accessibility::XAccessibleTextMarkup> xTextMarkup(xText, + css::uno::UNO_QUERY); + if (xTextMarkup.is()) + { + bool bInvalidSpelling = false; + const sal_Int32 nMarkupCount( + xTextMarkup->getTextMarkupCount(css::text::TextMarkupType::SPELLCHECK)); + for (sal_Int32 nMarkupIndex = 0; nMarkupIndex < nMarkupCount; ++nMarkupIndex) + { + const css::accessibility::TextSegment aTextSegment + = xTextMarkup->getTextMarkup(nMarkupIndex, css::text::TextMarkupType::SPELLCHECK); + const sal_Int32 nStartOffsetTextMarkup = aTextSegment.SegmentStart; + const sal_Int32 nEndOffsetTextMarkup = aTextSegment.SegmentEnd; + if (nStartOffsetTextMarkup <= nOffset) + { + if (nOffset < nEndOffsetTextMarkup) + { + // offset is inside invalid spelling + rStartOffset = ::std::max(rStartOffset, nStartOffsetTextMarkup); + rEndOffset = ::std::min(rEndOffset, nEndOffsetTextMarkup); + bInvalidSpelling = true; + break; + } + else + { + rStartOffset = ::std::max(rStartOffset, nEndOffsetTextMarkup); + } + } + else + { + rEndOffset = ::std::min(rEndOffset, nStartOffsetTextMarkup); + } + } + + if (bInvalidSpelling) + sAttributes += u"invalid:spelling;"_ustr; + } + return sAttributes; } commit 15a6e23c4fc160c50a316da3d18980a02fc10ce8 Author: Michael Weghorn <m.wegh...@posteo.de> AuthorDate: Tue Oct 17 14:16:54 2023 +0200 Commit: Michael Weghorn <m.wegh...@posteo.de> CommitDate: Wed Oct 18 12:48:49 2023 +0200 tdf#157696 qt a11y: Move handling for text attr offsets to helper Add a new method `AccessibleTextAttributeHelper::GetIAccessible2TextAttributes` and move some more of the logic from `QtAccessibleWidget::attributes` there to prepare adding handling for spelling errors via the "invalid:spelling" IAccessible2 text attribute and for reuse in winaccessibility. Change-Id: I3b4a89ee680437fa2c35c429639b372a55f5a4b1 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/158088 Tested-by: Jenkins Reviewed-by: Michael Weghorn <m.wegh...@posteo.de> diff --git a/include/vcl/accessibility/AccessibleTextAttributeHelper.hxx b/include/vcl/accessibility/AccessibleTextAttributeHelper.hxx index 6f8ef6dab66e..8c4b43b99e11 100644 --- a/include/vcl/accessibility/AccessibleTextAttributeHelper.hxx +++ b/include/vcl/accessibility/AccessibleTextAttributeHelper.hxx @@ -19,6 +19,7 @@ #pragma once +#include <com/sun/star/accessibility/XAccessibleText.hpp> #include <com/sun/star/beans/PropertyValue.hdl> #include <com/sun/star/uno/Sequence.hxx> #include <rtl/ustring.hxx> @@ -34,6 +35,19 @@ public: */ static OUString ConvertUnoToIAccessible2TextAttributes( const css::uno::Sequence<css::beans::PropertyValue>& rUnoAttributes); + + /** + * Get the IAccessible2 text attributes and the span of the attributes at the given index. + * @param xText The interace to query for the information. + * @param nOffset Character offset for which to retrieve the information. + * @param rStartOffset Out param that is set to the start index of the attribute run. + * @param rEndOffset Out param that is set to the end index of the attribute run. + * @return IAccessible2 text attributes at the given character offset. + */ + static OUString + GetIAccessible2TextAttributes(css::uno::Reference<css::accessibility::XAccessibleText> xText, + sal_Int32 nOffset, sal_Int32& rStartOffset, + sal_Int32& rEndOffset); }; /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */ diff --git a/vcl/qt5/QtAccessibleWidget.cxx b/vcl/qt5/QtAccessibleWidget.cxx index cd50af4aed9f..02a46147ce99 100644 --- a/vcl/qt5/QtAccessibleWidget.cxx +++ b/vcl/qt5/QtAccessibleWidget.cxx @@ -882,15 +882,8 @@ QString QtAccessibleWidget::attributes(int offset, int* startOffset, int* endOff return QString(); } - const Sequence<PropertyValue> attribs - = xText->getCharacterAttributes(offset, Sequence<OUString>()); - const OUString aRet - = AccessibleTextAttributeHelper::ConvertUnoToIAccessible2TextAttributes(attribs); - - accessibility::TextSegment aAttributeRun - = xText->getTextAtIndex(offset, accessibility::AccessibleTextType::ATTRIBUTE_RUN); - *startOffset = aAttributeRun.SegmentStart; - *endOffset = aAttributeRun.SegmentEnd; + const OUString aRet = AccessibleTextAttributeHelper::GetIAccessible2TextAttributes( + xText, offset, *startOffset, *endOffset); return toQString(aRet); } diff --git a/vcl/source/accessibility/AccessibleTextAttributeHelper.cxx b/vcl/source/accessibility/AccessibleTextAttributeHelper.cxx index ccd900e9edc1..5862b96a86c6 100644 --- a/vcl/source/accessibility/AccessibleTextAttributeHelper.cxx +++ b/vcl/source/accessibility/AccessibleTextAttributeHelper.cxx @@ -19,6 +19,7 @@ #include <vcl/accessibility/AccessibleTextAttributeHelper.hxx> +#include <com/sun/star/accessibility/AccessibleTextType.hpp> #include <com/sun/star/awt/FontSlant.hpp> #include <com/sun/star/awt/FontStrikeout.hpp> #include <com/sun/star/awt/FontUnderline.hpp> @@ -294,4 +295,22 @@ OUString AccessibleTextAttributeHelper::ConvertUnoToIAccessible2TextAttributes( return aRet; } +OUString AccessibleTextAttributeHelper::GetIAccessible2TextAttributes( + css::uno::Reference<css::accessibility::XAccessibleText> xText, sal_Int32 nOffset, + sal_Int32& rStartOffset, sal_Int32& rEndOffset) +{ + assert(xText.is()); + + const css::uno::Sequence<css::beans::PropertyValue> attribs + = xText->getCharacterAttributes(nOffset, css::uno::Sequence<OUString>()); + const OUString sAttributes = ConvertUnoToIAccessible2TextAttributes(attribs); + + css::accessibility::TextSegment aAttributeRun + = xText->getTextAtIndex(nOffset, css::accessibility::AccessibleTextType::ATTRIBUTE_RUN); + rStartOffset = aAttributeRun.SegmentStart; + rEndOffset = aAttributeRun.SegmentEnd; + + return sAttributes; +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab cinoptions=b1,g0,N-s cinkeys+=0=break: */