lok: a11y: send list item prefix length to client

Implemented getListPrefixSize function which relies on
UNO_NAME_NUMBERING_LEVEL, UNO_NAME_NUMBERING character attributes.
The former provides the list item level, the latter is a boolean that
says if a prefix (bullet/number) is present or not for the list item.
It has been needed to modify
SwAccessibleParagraph::_getSupplementalAttributesImpl so that it
returns such properties for list item only and not for simple
paragraph too. In fact for a simple paragraph the default value for
the level property was returned which is 0 exactly the same value for
top list item.

Change-Id: Ia651af4d4b2372eed42c90b0752e16fd47a4fdec
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/156816
Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
Reviewed-by: Gökay ŞATIR <gokaysatir@collabora.com>
(cherry picked from commit 038903d2e0)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157780
Tested-by: Jenkins
Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com>
This commit is contained in:
Marco Cecchetti 2023-09-03 18:47:30 +02:00 committed by Caolán McNamara
parent f1cb3bb773
commit 70cddea8cb
4 changed files with 86 additions and 5 deletions

View file

@ -932,9 +932,11 @@ typedef enum
* "position": N
* "start": N1
* "end": N2
* "listPrefixLength": L
* }
* where N is the position of the text cursor inside the focused paragraph,
* and [N1,N2] is the range of the text selection inside the focused paragraph.
* In case the paragraph is a list item, L is the length of the bullet/number prefix.
*/
LOK_CALLBACK_A11Y_FOCUS_CHANGED = 62,

View file

@ -67,6 +67,7 @@
#include <com/sun/star/awt/FontSlant.hpp>
#include <comphelper/diagnose_ex.hxx>
#include <editeng/unoprnms.hxx>
#include <tools/urlobj.hxx>
#include <unotools/tempfile.hxx>
#include <svtools/soerr.hxx>
@ -409,6 +410,42 @@ void aboutEvent(std::string msg, const accessibility::AccessibleEventObject& aEv
}
}
sal_Int32 getListPrefixSize(const uno::Reference<css::accessibility::XAccessibleText>& xAccText)
{
if (!xAccText.is())
return 0;
OUString sText = xAccText->getText();
sal_Int32 nLength = sText.getLength();
if (nLength <= 0)
return 0;
css::uno::Sequence< css::beans::PropertyValue > aRunAttributeList;
css::uno::Sequence< OUString > aRequestedAttributes = {UNO_NAME_NUMBERING_LEVEL, UNO_NAME_NUMBERING};
aRunAttributeList = xAccText->getCharacterAttributes(0, aRequestedAttributes);
sal_Int16 nLevel = -1;
bool bIsCounted = false;
for (const auto& attribute: aRunAttributeList)
{
if (attribute.Name.isEmpty())
continue;
if (attribute.Name == UNO_NAME_NUMBERING_LEVEL)
attribute.Value >>= nLevel;
else if (attribute.Name == UNO_NAME_NUMBERING)
attribute.Value >>= bIsCounted;
}
if (nLevel < 0 || !bIsCounted)
return 0;
css::accessibility::TextSegment aTextSegment =
xAccText->getTextAtIndex(0, css::accessibility::AccessibleTextType::ATTRIBUTE_RUN);
SAL_INFO("lok.a11y", "getListPrefixSize: prefix: " << aTextSegment.SegmentText << ", level: " << nLevel);
return aTextSegment.SegmentEnd;
}
void aboutTextFormatting(std::string msg, const uno::Reference<css::accessibility::XAccessibleText>& xAccText)
{
if (!xAccText.is())
@ -483,6 +520,22 @@ void aboutTextFormatting(std::string msg, const uno::Reference<css::accessibilit
attribute.Value >>= nValue;
sValue = OUString::number(nValue);
}
else if (attribute.Name == UNO_NAME_NUMBERING_LEVEL)
{
sal_Int16 nValue(-1);
attribute.Value >>= nValue;
sValue = OUString::number(nValue);
}
else if (attribute.Name == UNO_NAME_NUMBERING)
{
bool bValue(false);
attribute.Value >>= bValue;
sValue = OUString::boolean(bValue);
}
else if (attribute.Name == UNO_NAME_NUMBERING_RULES)
{
attribute.Value >>= sValue;
}
if (!sValue.isEmpty())
{
@ -501,12 +554,14 @@ void aboutTextFormatting(std::string msg, const uno::Reference<css::accessibilit
}
void aboutParagraph(std::string msg, const OUString& rsParagraphContent, sal_Int32 nCaretPosition,
sal_Int32 nSelectionStart, sal_Int32 nSelectionEnd, bool force = false)
sal_Int32 nSelectionStart, sal_Int32 nSelectionEnd, sal_Int32 nListPrefixLength,
bool force = false)
{
SAL_INFO("lok.a11y", msg << ": "
"\n text content: \"" << rsParagraphContent << "\""
"\n caret pos: " << nCaretPosition
<< "\n selection: start: " << nSelectionStart << ", end: " << nSelectionEnd
<< "\n list prefix length: " << nListPrefixLength
<< "\n force: " << force
);
}
@ -521,7 +576,8 @@ void aboutParagraph(std::string msg, const uno::Reference<css::accessibility::XA
sal_Int32 nCaretPosition = xAccText->getCaretPosition();
sal_Int32 nSelectionStart = xAccText->getSelectionStart();
sal_Int32 nSelectionEnd = xAccText->getSelectionEnd();
aboutParagraph(msg, sText, nCaretPosition, nSelectionStart, nSelectionEnd, force);
sal_Int32 nListPrefixLength = getListPrefixSize(xAccText);
aboutParagraph(msg, sText, nCaretPosition, nSelectionStart, nSelectionEnd, nListPrefixLength, force);
}
void aboutFocusedCellChanged(sal_Int32 nOutCount, const std::vector<TableSizeType>& aInList,
@ -557,6 +613,7 @@ class LOKDocumentFocusListener :
sal_Int32 m_nCaretPosition;
sal_Int32 m_nSelectionStart;
sal_Int32 m_nSelectionEnd;
sal_Int32 m_nListPrefixLength;
uno::Reference<accessibility::XAccessibleTable> m_xLastTable;
OUString m_sSelectedText;
bool m_bIsEditingCell;
@ -640,6 +697,7 @@ LOKDocumentFocusListener::LOKDocumentFocusListener(const SfxViewShell* pViewShel
, m_nCaretPosition(0)
, m_nSelectionStart(0)
, m_nSelectionEnd(0)
, m_nListPrefixLength(0)
, m_bIsEditingCell(false)
{
}
@ -651,6 +709,8 @@ void LOKDocumentFocusListener::paragraphPropertiesToTree(boost::property_tree::p
aPayloadTree.put("position", m_nCaretPosition);
aPayloadTree.put("start", bLeftToRight ? m_nSelectionStart : m_nSelectionEnd);
aPayloadTree.put("end", bLeftToRight ? m_nSelectionEnd : m_nSelectionStart);
if (m_nListPrefixLength > 0)
aPayloadTree.put("listPrefixLength", m_nListPrefixLength);
if (force)
aPayloadTree.put("force", 1);
}
@ -668,7 +728,8 @@ OUString LOKDocumentFocusListener::getFocusedParagraph() const
{
aboutView("LOKDocumentFocusListener::getFocusedParagraph", this, m_pViewShell);
aboutParagraph("LOKDocumentFocusListener::getFocusedParagraph",
m_sFocusedParagraph, m_nCaretPosition, m_nSelectionStart, m_nSelectionEnd);
m_sFocusedParagraph, m_nCaretPosition,
m_nSelectionStart, m_nSelectionEnd, m_nListPrefixLength);
std::string aPayload;
paragraphPropertiesToJson(aPayload);
@ -710,7 +771,8 @@ void LOKDocumentFocusListener::notifyFocusedParagraphChanged(bool force)
if (m_pViewShell)
{
aboutParagraph("LOKDocumentFocusListener::notifyFocusedParagraphChanged",
m_sFocusedParagraph, m_nCaretPosition, m_nSelectionStart, m_nSelectionEnd, force);
m_sFocusedParagraph, m_nCaretPosition,
m_nSelectionStart, m_nSelectionEnd, m_nListPrefixLength, force);
m_pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_A11Y_FOCUS_CHANGED, aPayload.c_str());
}
@ -796,7 +858,8 @@ void LOKDocumentFocusListener::notifyFocusedCellChanged(
{
aboutFocusedCellChanged(nOutCount, aInList, nRow, nCol, nRowSpan, nColSpan);
aboutParagraph("LOKDocumentFocusListener::notifyFocusedCellChanged: paragraph: ",
m_sFocusedParagraph, m_nCaretPosition, m_nSelectionStart, m_nSelectionEnd, false);
m_sFocusedParagraph, m_nCaretPosition, m_nSelectionStart,
m_nSelectionEnd, m_nListPrefixLength, false);
m_pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_A11Y_FOCUSED_CELL_CHANGED, aPayload.c_str());
}
@ -826,6 +889,7 @@ bool LOKDocumentFocusListener::updateParagraphInfo(const uno::Reference<css::acc
m_nCaretPosition = nCaretPosition;
m_nSelectionStart = xAccText->getSelectionStart();
m_nSelectionEnd = xAccText->getSelectionEnd();
m_nListPrefixLength = getListPrefixSize(xAccText);
// In case only caret position or text selection are different we can rely on specific events.
if (m_sFocusedParagraph != sText)

View file

@ -910,6 +910,7 @@ static uno::Sequence< OUString > const & getSupplementalAttributeNames()
{
// sorted list of strings
UNO_NAME_NUMBERING_LEVEL,
UNO_NAME_NUMBERING,
UNO_NAME_NUMBERING_RULES,
UNO_NAME_PARA_ADJUST,
UNO_NAME_PARA_BOTTOM_MARGIN,
@ -1360,6 +1361,9 @@ uno::Sequence<PropertyValue> SwAccessibleParagraph::getCharacterAttributes(
tAccParaPropValMap aRunAttrSeq;
_getRunAttributesImpl( nIndex, aNames, aRunAttrSeq );
// this allows to request one or more supplemental attributes, only
bSupplementalMode = bSupplementalMode || aDefAttrSeq.empty() || aRunAttrSeq.empty();
// merge default and run attributes
std::vector< PropertyValue > aValues( aDefAttrSeq.size() );
sal_Int32 i = 0;
@ -1765,6 +1769,7 @@ void SwAccessibleParagraph::_getSupplementalAttributesImpl(
if ( pTextNode->HasBullet() || pTextNode->HasNumber() )
{
aSet.Put( pTextNode->GetAttr(RES_PARATR_LIST_LEVEL) );
aSet.Put( pTextNode->GetAttr(RES_PARATR_LIST_ISCOUNTED) );
}
aSet.Put( pTextNode->SwContentNode::GetAttr(RES_UL_SPACE) );
aSet.Put( pTextNode->SwContentNode::GetAttr(RES_MARGIN_FIRSTLINE) );
@ -1778,6 +1783,15 @@ void SwAccessibleParagraph::_getSupplementalAttributesImpl(
aSwMapProvider.GetPropertyMapEntries( PROPERTY_MAP_ACCESSIBILITY_TEXT_ATTRIBUTE ) );
for (const auto & rEntry : pPropMap)
{
// For a paragraph, list level property is not set but when queried the returned default
// value is 0, exactly the same value of top level list item; that prevents using
// list level property for discerning simple paragraph from list item;
// the following check allows not to return the list level property at all
// when we are dealing with a simple paragraph
if ((rEntry.nWID == RES_PARATR_LIST_LEVEL || rEntry.nWID == RES_PARATR_LIST_ISCOUNTED) &&
!aSet.HasItem( rEntry.nWID ))
continue;
const SfxPoolItem* pItem = aSet.GetItem( rEntry.nWID );
if ( pItem )
{

View file

@ -533,6 +533,7 @@
{ UNO_NAME_CHAR_UNDERLINE_COMPLEX_COLOR, RES_CHRATR_UNDERLINE, cppu::UnoType<css::util::XComplexColor>::get(), PropertyAttribute::MAYBEVOID, MID_TL_COMPLEX_COLOR}, \
{ UNO_NAME_CHAR_WEIGHT, RES_CHRATR_WEIGHT , cppu::UnoType<float>::get(), PropertyAttribute::MAYBEVOID, MID_WEIGHT}, \
{ UNO_NAME_NUMBERING_LEVEL, RES_PARATR_LIST_LEVEL,cppu::UnoType<sal_Int16>::get(), PropertyAttribute::MAYBEVOID, 0}, \
{ UNO_NAME_NUMBERING, RES_PARATR_LIST_ISCOUNTED, cppu::UnoType<bool>::get(), PropertyAttribute::MAYBEVOID, 0}, \
{ UNO_NAME_CHAR_UNDERLINE, RES_CHRATR_UNDERLINE , cppu::UnoType<sal_Int16>::get(), PropertyAttribute::MAYBEVOID, MID_TL_STYLE}, \
{ UNO_NAME_NUMBERING_RULES, RES_PARATR_NUMRULE,cppu::UnoType<sal_Int16>::get(), PropertyAttribute::MAYBEVOID, CONVERT_TWIPS}, \
{ UNO_NAME_PARA_ADJUST, RES_PARATR_ADJUST, cppu::UnoType<sal_Int16>::get(), PropertyAttribute::MAYBEVOID, MID_PARA_ADJUST}, \