sc/source/ui/Accessibility/AccessibleCell.cxx     |   27 ++--
 sc/source/ui/Accessibility/AccessibleCellBase.cxx |  128 ++++++++--------------
 sc/source/ui/Accessibility/AccessibleDocument.cxx |   14 +-
 sc/source/ui/inc/AccessibleCell.hxx               |    4 
 sc/source/ui/inc/AccessibleCellBase.hxx           |    7 -
 sc/source/ui/inc/AccessibleDocument.hxx           |    3 
 6 files changed, 74 insertions(+), 109 deletions(-)

New commits:
commit 6147a4ca97c55bd3c6c8fb4ce42105649f7eab48
Author:     Michael Weghorn <[email protected]>
AuthorDate: Thu Mar 5 13:30:30 2026 +0100
Commit:     Michael Weghorn <[email protected]>
CommitDate: Fri Mar 6 07:16:17 2026 +0100

    sc a11y: Switch to override new extended attr helper for doc
    
    Override the OAccessible::implGetExtendedAttributes
    base class method newly introduced in
    
        Change-Id: Ie66f135fbf6cdc98c7cdca27fa3f5fe7db7f9a74
        Author: Michael Weghorn <[email protected]>
        Date:   Thu Mar 5 12:12:45 2026 +0100
    
            a11y: Introduce helper to implement XAccessibleExtendedAttributes 
logic
    
    instead of manually implementing
    XAccessibleExtendedAttributes::getExtendedAttributes, to
    unify/deduplicate the string concatenation and locking logic
    by having it implemented (only) in the base class implementation.
    
    Change-Id: I791a26e50dc00d4330e92f913b32d0de919ff9de
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/201038
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <[email protected]>

diff --git a/sc/source/ui/Accessibility/AccessibleDocument.cxx 
b/sc/source/ui/Accessibility/AccessibleDocument.cxx
index 5ff99a1cf36a..c7b98ae1a354 100644
--- a/sc/source/ui/Accessibility/AccessibleDocument.cxx
+++ b/sc/source/ui/Accessibility/AccessibleDocument.cxx
@@ -2084,20 +2084,18 @@ ScAddress   ScAccessibleDocument::GetCurCellAddress() 
const
     return mpViewShell ? mpViewShell->GetViewData().GetCurPos() : ScAddress();
 }
 
-OUString SAL_CALL ScAccessibleDocument::getExtendedAttributes()
+std::unordered_map<OUString, OUString> 
ScAccessibleDocument::implGetExtendedAttributes()
 {
-    SolarMutexGuard g;
-
     sal_uInt16 sheetIndex;
     OUString sSheetName;
     sheetIndex = getVisibleTable();
     if(GetDocument()==nullptr)
-        return OUString();
+        return {};
+
     GetDocument()->GetName(sheetIndex,sSheetName);
-    OUString sValue = "page-name:" + sSheetName +
-        ";page-number:" + OUString::number(sheetIndex+1) +
-        ";total-pages:" + OUString::number(GetDocument()->GetTableCount()) + 
";";
-    return sValue;
+    return { { u"page-name"_ustr, sSheetName },
+             { u"page-number"_ustr, OUString::number(sheetIndex + 1) },
+             { u"total-pages"_ustr, 
OUString::number(GetDocument()->GetTableCount()) } };
 }
 
 sal_Int32 SAL_CALL ScAccessibleDocument::getForeground(  )
diff --git a/sc/source/ui/inc/AccessibleDocument.hxx 
b/sc/source/ui/inc/AccessibleDocument.hxx
index 90fedc526559..c95257070ea1 100644
--- a/sc/source/ui/inc/AccessibleDocument.hxx
+++ b/sc/source/ui/inc/AccessibleDocument.hxx
@@ -92,7 +92,6 @@ public:
     virtual OUString SAL_CALL
         getAccessibleName() override;
 
-    virtual OUString SAL_CALL getExtendedAttributes() override ;
     ///=====  XAccessibleSelection  ===========================================
 
     virtual void SAL_CALL
@@ -165,6 +164,8 @@ public:
         GetAccessibleSpreadsheet();
 
 protected:
+    virtual std::unordered_map<OUString, OUString> implGetExtendedAttributes() 
override;
+
     /// Return this object's description.
     virtual OUString
         createAccessibleDescription() override;
commit bbd64edb27c3ed01ca451f2ab23d055f93c98b80
Author:     Michael Weghorn <[email protected]>
AuthorDate: Thu Mar 5 13:15:44 2026 +0100
Commit:     Michael Weghorn <[email protected]>
CommitDate: Fri Mar 6 07:16:10 2026 +0100

    sc a11y: Switch to override new extended attr helper for cell
    
    Override the OAccessible::implGetExtendedAttributes
    base class method newly introduced in
    
        Change-Id: Ie66f135fbf6cdc98c7cdca27fa3f5fe7db7f9a74
        Author: Michael Weghorn <[email protected]>
        Date:   Thu Mar 5 12:12:45 2026 +0100
    
            a11y: Introduce helper to implement XAccessibleExtendedAttributes 
logic
    
    instead of manually implementing
    XAccessibleExtendedAttributes::getExtendedAttributes, to
    unify/deduplicate the string concatenation and locking logic
    by having it implemented (only) in the base class implementation.
    
    Switch the helper methods accordingly and drop custom
    mutex locking and checking that the object is still
    alive, as the base class takes care of this now in
    OAccessible::getExtendedAttributes.
    
    Change-Id: I740d7968ed732b092604a69b5c8a1b2709caa4f0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/201037
    Tested-by: Jenkins
    Reviewed-by: Michael Weghorn <[email protected]>

diff --git a/sc/source/ui/Accessibility/AccessibleCell.cxx 
b/sc/source/ui/Accessibility/AccessibleCell.cxx
index 8344029c3f83..340fe5a0ba43 100644
--- a/sc/source/ui/Accessibility/AccessibleCell.cxx
+++ b/sc/source/ui/Accessibility/AccessibleCell.cxx
@@ -463,9 +463,9 @@ static OUString ReplaceFourChar(const OUString& oldOUString)
         .replaceAll(u":", u"\:");
 }
 
-OUString SAL_CALL ScAccessibleCell::getExtendedAttributes()
+std::unordered_map<OUString, OUString> 
ScAccessibleCell::implGetExtendedAttributes()
 {
-    SolarMutexGuard aGuard;
+    std::unordered_map<OUString, OUString> aAttributes;
 
     // report row and column index text via attributes as specified in ARIA 
which map
     // to attributes of the same name for AT-SPI2, IAccessible2, UIA
@@ -473,30 +473,29 @@ OUString SAL_CALL 
ScAccessibleCell::getExtendedAttributes()
     // https://www.w3.org/TR/core-aam-1.2/#ariaColIndexText
     const OUString sRowIndexText = maCellAddress.Format(ScRefFlags::ROW_VALID);
     const OUString sColIndexText = maCellAddress.Format(ScRefFlags::COL_VALID);
-    OUString sAttributes = "rowindextext:" + sRowIndexText + ";colindextext:" 
+ sColIndexText + ";";
+    aAttributes.emplace(u"rowindextext"_ustr, sRowIndexText);
+    aAttributes.emplace(u"colindextext"_ustr, sColIndexText);
 
     if (mpViewShell)
     {
         const OUString sFormula = mpViewShell->GetFormula(maCellAddress) ;
         if (!sFormula.isEmpty())
-            sAttributes += u"Formula:" + ReplaceFourChar(sFormula.copy(1)) + 
u";";
+            aAttributes.emplace(u"Formula"_ustr, 
ReplaceFourChar(sFormula.copy(1)));
 
-        sAttributes += "Note:" + ReplaceFourChar(GetAllDisplayNote()) + ";" +
-            getShadowAttrs() + //the string returned contains the spliter ";"
-            getBorderAttrs();//the string returned contains the spliter ";"
+        aAttributes.emplace(u"Note"_ustr, 
ReplaceFourChar(GetAllDisplayNote()));
+        for (const auto& rAttr : getShadowAttrs())
+            aAttributes.insert(rAttr);
+        for (const auto& rAttr : getBorderAttrs())
+            aAttributes.insert(rAttr);
         //end of cell attributes
         if( mpDoc )
         {
-            sAttributes += "isdropdown:";
-            if( IsDropdown() )
-                sAttributes += "true";
-            else
-                sAttributes += "false";
-            sAttributes += ";";
+            const OUString sDropDownValue = IsDropdown() ? u"true"_ustr : 
u"false"_ustr;
+            aAttributes.emplace(u"isdropdown"_ustr, sDropDownValue);
         }
     }
 
-    return sAttributes;
+    return aAttributes;
 }
 
 // cell has its own ParaIndent property, so when calling character attributes 
on cell, the ParaIndent should replace the ParaLeftMargin if its value is not 
zero.
diff --git a/sc/source/ui/Accessibility/AccessibleCellBase.cxx 
b/sc/source/ui/Accessibility/AccessibleCellBase.cxx
index dce3ff27ab62..588a7e0459d1 100644
--- a/sc/source/ui/Accessibility/AccessibleCellBase.cxx
+++ b/sc/source/ui/Accessibility/AccessibleCellBase.cxx
@@ -292,10 +292,8 @@ OUString ScAccessibleCellBase::GetNote() const
     return sNote;
 }
 
-OUString ScAccessibleCellBase::getShadowAttrs() const
+std::unordered_map<OUString, OUString> ScAccessibleCellBase::getShadowAttrs() 
const
 {
-    SolarMutexGuard aGuard;
-    ensureAlive();
     table::ShadowFormat aShadowFmt;
     if (mpDoc)
     {
@@ -328,10 +326,8 @@ OUString ScAccessibleCellBase::getShadowAttrs() const
             }
         }
     }
-    //construct shadow attributes string
-    OUString sShadowAttrs(u"Shadow:"_ustr);
+    const OUString sShadowAttrName(u"Shadow"_ustr);
     OUString sInnerSplit(u","_ustr);
-    OUString sOuterSplit(u";"_ustr);
     sal_Int32 nLocationVal = 0;
     switch( aShadowFmt.Location )
     {
@@ -353,29 +349,19 @@ OUString ScAccessibleCellBase::getShadowAttrs() const
     //if there is no shadow property for the cell
     if ( nLocationVal == 0 )
     {
-        sShadowAttrs += sOuterSplit;
-        return sShadowAttrs;
+        return { { sShadowAttrName, u""_ustr } };
     }
     //else return all the shadow properties
-    sShadowAttrs += "Location=" +
-        OUString::number( nLocationVal ) +
-        sInnerSplit +
-        "ShadowWidth=" +
-        OUString::number( static_cast<sal_Int32>(aShadowFmt.ShadowWidth) ) +
-        sInnerSplit +
-        "IsTransparent=" +
-        OUString::number( static_cast<int>(aShadowFmt.IsTransparent) ) +
-        sInnerSplit +
-        "Color=" +
-        OUString::number( aShadowFmt.Color ) +
-        sOuterSplit;
-    return sShadowAttrs;
+    const OUString sAttrValue
+        = "Location=" + OUString::number(nLocationVal) + sInnerSplit + 
"ShadowWidth="
+          + OUString::number(static_cast<sal_Int32>(aShadowFmt.ShadowWidth)) + 
sInnerSplit
+          + "IsTransparent=" + 
OUString::number(static_cast<int>(aShadowFmt.IsTransparent))
+          + sInnerSplit + "Color=" + OUString::number(aShadowFmt.Color);
+    return { { sShadowAttrName, sAttrValue } };
 }
 
-OUString ScAccessibleCellBase::getBorderAttrs()
+std::unordered_map<OUString, OUString> ScAccessibleCellBase::getBorderAttrs()
 {
-    SolarMutexGuard aGuard;
-    ensureAlive();
     table::BorderLine aTopBorder;
     table::BorderLine aBottomBorder;
     table::BorderLine aLeftBorder;
@@ -432,92 +418,74 @@ OUString ScAccessibleCellBase::getBorderAttrs()
         aRightBorder.OuterLineWidth = DEFAULT_LINE_WIDTH;
     }
 
-    //construct border attributes string
-    OUString sBorderAttrs;
+    std::unordered_map<OUString, OUString> aBorderAttrs;
     OUString sInnerSplit(u","_ustr);
-    OUString sOuterSplit(u";"_ustr);
     //top border
     //if top of the cell has no border
     if ( aTopBorder.InnerLineWidth == 0 && aTopBorder.OuterLineWidth == 0 )
     {
-        sBorderAttrs += "TopBorder:;";
+        aBorderAttrs.emplace(u"TopBorder"_ustr, u""_ustr);
     }
     else//add all the border properties to the return string.
     {
-        sBorderAttrs += "TopBorder:Color=" +
-            OUString::number( aTopBorder.Color ) +
-            sInnerSplit +
-            "InnerLineWidth=" +
-            OUString::number( 
static_cast<sal_Int32>(aTopBorder.InnerLineWidth) ) +
-            sInnerSplit +
-            "OuterLineWidth=" +
-            OUString::number( 
static_cast<sal_Int32>(aTopBorder.OuterLineWidth) ) +
-            sInnerSplit +
-            "LineDistance=" +
-            OUString::number( static_cast<sal_Int32>(aTopBorder.LineDistance) 
) +
-            sOuterSplit;
+        aBorderAttrs.emplace(
+            u"TopBorder"_ustr,
+            u"Color=" + OUString::number(aTopBorder.Color) + sInnerSplit + 
"InnerLineWidth="
+                + 
OUString::number(static_cast<sal_Int32>(aTopBorder.InnerLineWidth)) + 
sInnerSplit
+                + "OuterLineWidth="
+                + 
OUString::number(static_cast<sal_Int32>(aTopBorder.OuterLineWidth)) + 
sInnerSplit
+                + "LineDistance="
+                + 
OUString::number(static_cast<sal_Int32>(aTopBorder.LineDistance)));
     }
     //bottom border
     if ( aBottomBorder.InnerLineWidth == 0 && aBottomBorder.OuterLineWidth == 
0 )
     {
-        sBorderAttrs += "BottomBorder:;";
+        aBorderAttrs.emplace(u"BottomBorder"_ustr, u""_ustr);
     }
     else
     {
-        sBorderAttrs += "BottomBorder:Color=" +
-            OUString::number( aBottomBorder.Color ) +
-            sInnerSplit +
-            "InnerLineWidth=" +
-            OUString::number( 
static_cast<sal_Int32>(aBottomBorder.InnerLineWidth) ) +
-            sInnerSplit +
-            "OuterLineWidth=" +
-            OUString::number( 
static_cast<sal_Int32>(aBottomBorder.OuterLineWidth) ) +
-            sInnerSplit +
-            "LineDistance=" +
-            OUString::number( 
static_cast<sal_Int32>(aBottomBorder.LineDistance) ) +
-            sOuterSplit;
+        aBorderAttrs.emplace(
+            u"BottomBorder"_ustr,
+            u"Color" + OUString::number(aBottomBorder.Color) + sInnerSplit + 
"InnerLineWidth="
+                + 
OUString::number(static_cast<sal_Int32>(aBottomBorder.InnerLineWidth))
+                + sInnerSplit + "OuterLineWidth="
+                + 
OUString::number(static_cast<sal_Int32>(aBottomBorder.OuterLineWidth))
+                + sInnerSplit + "LineDistance="
+                + 
OUString::number(static_cast<sal_Int32>(aBottomBorder.LineDistance)));
     }
     //left border
     if ( aLeftBorder.InnerLineWidth == 0 && aLeftBorder.OuterLineWidth == 0 )
     {
-        sBorderAttrs += "LeftBorder:;";
+        aBorderAttrs.emplace(u"LeftBorder"_ustr, u""_ustr);
     }
     else
     {
-        sBorderAttrs += "LeftBorder:Color=" +
-            OUString::number( aLeftBorder.Color ) +
-            sInnerSplit +
-            "InnerLineWidth=" +
-            OUString::number( 
static_cast<sal_Int32>(aLeftBorder.InnerLineWidth) ) +
-            sInnerSplit +
-            "OuterLineWidth=" +
-            OUString::number( 
static_cast<sal_Int32>(aLeftBorder.OuterLineWidth) ) +
-            sInnerSplit +
-            "LineDistance=" +
-            OUString::number( static_cast<sal_Int32>(aLeftBorder.LineDistance) 
) +
-            sOuterSplit;
+        aBorderAttrs.emplace(
+            u"LeftBorder"_ustr,
+            u"Color=" + OUString::number(aLeftBorder.Color) + sInnerSplit + 
"InnerLineWidth="
+                + 
OUString::number(static_cast<sal_Int32>(aLeftBorder.InnerLineWidth)) + 
sInnerSplit
+                + "OuterLineWidth="
+                + 
OUString::number(static_cast<sal_Int32>(aLeftBorder.OuterLineWidth)) + 
sInnerSplit
+                + "LineDistance="
+                + 
OUString::number(static_cast<sal_Int32>(aLeftBorder.LineDistance)));
     }
     //right border
     if ( aRightBorder.InnerLineWidth == 0 && aRightBorder.OuterLineWidth == 0 )
     {
-        sBorderAttrs += "RightBorder:;";
+        aBorderAttrs.emplace(u"RightBorder"_ustr, u""_ustr);
     }
     else
     {
-        sBorderAttrs += "RightBorder:Color=" +
-            OUString::number( aRightBorder.Color ) +
-            sInnerSplit +
-            "InnerLineWidth=" +
-            OUString::number( 
static_cast<sal_Int32>(aRightBorder.InnerLineWidth) ) +
-            sInnerSplit +
-            "OuterLineWidth=" +
-            OUString::number( 
static_cast<sal_Int32>(aRightBorder.OuterLineWidth) ) +
-            sInnerSplit +
-            "LineDistance=" +
-            OUString::number( 
static_cast<sal_Int32>(aRightBorder.LineDistance) ) +
-            sOuterSplit;
+        aBorderAttrs.emplace(
+            u"RightBorder"_ustr,
+            u"Color=" + OUString::number(aRightBorder.Color) + sInnerSplit + 
"InnerLineWidth="
+                + 
OUString::number(static_cast<sal_Int32>(aRightBorder.InnerLineWidth))
+                + sInnerSplit + "OuterLineWidth="
+                + 
OUString::number(static_cast<sal_Int32>(aRightBorder.OuterLineWidth))
+                + sInnerSplit + "LineDistance="
+                + 
OUString::number(static_cast<sal_Int32>(aRightBorder.LineDistance)));
     }
-    return sBorderAttrs;
+    return aBorderAttrs;
 }
 //end of cell attributes
 
diff --git a/sc/source/ui/inc/AccessibleCell.hxx 
b/sc/source/ui/inc/AccessibleCell.hxx
index 6e6135495e45..410de8bb7969 100644
--- a/sc/source/ui/inc/AccessibleCell.hxx
+++ b/sc/source/ui/inc/AccessibleCell.hxx
@@ -84,6 +84,8 @@ public:
     virtual void SAL_CALL grabFocus(  ) override;
 
 protected:
+    virtual std::unordered_map<OUString, OUString> implGetExtendedAttributes() 
override;
+
     /// Return the object's current bounding box relative to the desktop.
     virtual AbsoluteScreenPixelRectangle GetBoundingBoxOnScreen() override;
 
@@ -111,8 +113,6 @@ public:
         css::accessibility::XAccessibleRelationSet> SAL_CALL
            getAccessibleRelationSet() override;
 
-    virtual OUString SAL_CALL getExtendedAttributes() override;
-
     // Override this method to handle cell's ParaIndent attribute specially.
     virtual css::uno::Sequence< css::beans::PropertyValue > SAL_CALL 
getCharacterAttributes( sal_Int32 nIndex, const css::uno::Sequence< OUString >& 
aRequestedAttributes ) override;
 private:
diff --git a/sc/source/ui/inc/AccessibleCellBase.hxx 
b/sc/source/ui/inc/AccessibleCellBase.hxx
index c14d3f644d89..8f641f879bce 100644
--- a/sc/source/ui/inc/AccessibleCellBase.hxx
+++ b/sc/source/ui/inc/AccessibleCellBase.hxx
@@ -93,10 +93,9 @@ protected:
 
     /// @throw css::uno::RuntimeException
     OUString GetAllDisplayNote() const;
-    /// @throw css::uno::RuntimeException
-    OUString getShadowAttrs() const;
-    /// @throw css::uno::RuntimeException
-    OUString getBorderAttrs();
+    std::unordered_map<OUString, OUString> getShadowAttrs() const;
+    std::unordered_map<OUString, OUString> getBorderAttrs();
+
 public:
     const ScAddress& GetCellAddress() const { return maCellAddress; }
 };

Reply via email to