include/LibreOfficeKit/LibreOfficeKitEnums.h |    2 
 sfx2/source/view/viewsh.cxx                  |   74 +++++++++++++++++++++++++--
 sw/source/core/access/accpara.cxx            |   14 +++++
 sw/source/core/unocore/unomapproperties.hxx  |    1 
 4 files changed, 86 insertions(+), 5 deletions(-)

New commits:
commit 70cddea8cb780f2fe0acdd15b72d13ce2d1ad649
Author:     Marco Cecchetti <marco.cecche...@collabora.com>
AuthorDate: Sun Sep 3 18:47:30 2023 +0200
Commit:     Caolán McNamara <caolan.mcnam...@collabora.com>
CommitDate: Sun Oct 22 15:25:19 2023 +0200

    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 <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Gökay ŞATIR <gokaysa...@collabora.com>
    (cherry picked from commit 038903d2e066de9525a3baffdd232484ef44ff51)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/157780
    Tested-by: Jenkins
    Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com>

diff --git a/include/LibreOfficeKit/LibreOfficeKitEnums.h 
b/include/LibreOfficeKit/LibreOfficeKitEnums.h
index e7f31c2a14fe..883a68ce09c6 100644
--- a/include/LibreOfficeKit/LibreOfficeKitEnums.h
+++ b/include/LibreOfficeKit/LibreOfficeKitEnums.h
@@ -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,
 
diff --git a/sfx2/source/view/viewsh.cxx b/sfx2/source/view/viewsh.cxx
index 5e437b45269a..68c99691fb4c 100644
--- a/sfx2/source/view/viewsh.cxx
+++ b/sfx2/source/view/viewsh.cxx
@@ -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)
diff --git a/sw/source/core/access/accpara.cxx 
b/sw/source/core/access/accpara.cxx
index 7226ea72d35d..96e58f35f1c3 100644
--- a/sw/source/core/access/accpara.cxx
+++ b/sw/source/core/access/accpara.cxx
@@ -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 )
             {
diff --git a/sw/source/core/unocore/unomapproperties.hxx 
b/sw/source/core/unocore/unomapproperties.hxx
index 323aa3b9ce46..2330ba8608e6 100644
--- a/sw/source/core/unocore/unomapproperties.hxx
+++ b/sw/source/core/unocore/unomapproperties.hxx
@@ -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}, \

Reply via email to