comphelper/source/misc/accessiblecomponenthelper.cxx |    3 -
 comphelper/source/misc/accessibleeventnotifier.cxx   |   17 ++++++-
 include/comphelper/accessiblecomponenthelper.hxx     |    3 -
 sc/source/ui/Accessibility/AccessibleDocument.cxx    |    2 
 vcl/unx/gtk3/a11y/atklistener.cxx                    |   42 +++++++++++++------
 5 files changed, 51 insertions(+), 16 deletions(-)

New commits:
commit 2361718a34ee4ef47901846cb35eea4552bca46b
Author:     Noel Grandin <noel.gran...@collabora.co.uk>
AuthorDate: Fri May 5 12:11:34 2023 +0200
Commit:     Noel Grandin <noel.gran...@collabora.co.uk>
CommitDate: Fri May 5 14:39:58 2023 +0200

    tdf#155149 Crash when exiting cell edit mode
    
    regression from
        commit 2dc240a82646fc23c673a6fd5a29ade934dd5b67
        Author: Noel Grandin <noel.gran...@collabora.co.uk>
        Date:   Tue May 2 14:47:43 2023 +0200
        improve AccessibleEventNotifier::addEvent
    and
        commit 3b7db802731826b6cc3b55100470b0c61c1f2dfa
        Author: Noel Grandin <noel.gran...@collabora.co.uk>
        Date:   Thu May 4 10:06:14 2023 +0200
        tdf#105404 [API CHANGE] add index to accessiblity change event
    
    (*) Send better index hints
    (*) Error check the index hints better
    (*) Convert asserts to warnings and fall back to old code when
        index hint is wrong.
    
    Change-Id: I8e752fc26e729c9c8926beb2c7b196f5418a147e
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/151419
    Tested-by: Jenkins
    Reviewed-by: Noel Grandin <noel.gran...@collabora.co.uk>

diff --git a/comphelper/source/misc/accessiblecomponenthelper.cxx 
b/comphelper/source/misc/accessiblecomponenthelper.cxx
index 816b3b69ee0c..07d05d31a31d 100644
--- a/comphelper/source/misc/accessiblecomponenthelper.cxx
+++ b/comphelper/source/misc/accessiblecomponenthelper.cxx
@@ -113,7 +113,7 @@ namespace comphelper
 
 
     void OCommonAccessibleComponent::NotifyAccessibleEvent( const sal_Int16 
_nEventId,
-        const Any& _rOldValue, const Any& _rNewValue )
+        const Any& _rOldValue, const Any& _rNewValue, sal_Int32 nIndexHint )
     {
         if ( !m_nClientId )
             // if we don't have a client id for the notifier, then we don't 
have listeners, then
@@ -126,6 +126,7 @@ namespace comphelper
         aEvent.EventId = _nEventId;
         aEvent.OldValue = _rOldValue;
         aEvent.NewValue = _rNewValue;
+        aEvent.IndexHint = nIndexHint;
 
         // let the notifier handle this event
         AccessibleEventNotifier::addEvent( m_nClientId, aEvent );
diff --git a/comphelper/source/misc/accessibleeventnotifier.cxx 
b/comphelper/source/misc/accessibleeventnotifier.cxx
index d146d11812ba..37c9edda2625 100644
--- a/comphelper/source/misc/accessibleeventnotifier.cxx
+++ b/comphelper/source/misc/accessibleeventnotifier.cxx
@@ -246,8 +246,21 @@ void AccessibleEventNotifier::addEvent( const TClientId 
_nClient, const Accessib
         return;
 
     // since we're synchronous, again, we want to notify immediately
-    aClientPos->second.notifyEach(aGuard, 
&XAccessibleEventListener::notifyEvent, _rEvent);
-
+    OInterfaceIteratorHelper4 aIt(aGuard, aClientPos->second);
+    // no need to hold lock here, and we don't want to hold lock while calling 
listeners
+    aGuard.unlock();
+    while (aIt.hasMoreElements())
+    {
+        try
+        {
+            aIt.next()->notifyEvent(_rEvent);
+        }
+        catch (Exception&)
+        {
+            // no assertion, because a broken access remote bridge or 
something like this
+            // can cause this exception
+        }
+    }
 }
 
 } // namespace comphelper
diff --git a/include/comphelper/accessiblecomponenthelper.hxx 
b/include/comphelper/accessiblecomponenthelper.hxx
index 2a840ea9e36e..328d61316b15 100644
--- a/include/comphelper/accessiblecomponenthelper.hxx
+++ b/include/comphelper/accessiblecomponenthelper.hxx
@@ -128,7 +128,8 @@ namespace comphelper
         void NotifyAccessibleEvent(
                     const sal_Int16 _nEventId,
                     const css::uno::Any& _rOldValue,
-                    const css::uno::Any& _rNewValue
+                    const css::uno::Any& _rNewValue,
+                    sal_Int32 nIndexHint = -1
                 );
 
         // life time control
diff --git a/sc/source/ui/Accessibility/AccessibleDocument.cxx 
b/sc/source/ui/Accessibility/AccessibleDocument.cxx
index 6d5dacede496..870851691a43 100644
--- a/sc/source/ui/Accessibility/AccessibleDocument.cxx
+++ b/sc/source/ui/Accessibility/AccessibleDocument.cxx
@@ -2136,6 +2136,7 @@ void ScAccessibleDocument::AddChild(const 
uno::Reference<XAccessible>& xAcc, boo
             aEvent.Source = uno::Reference<XAccessibleContext>(this);
             aEvent.EventId = AccessibleEventId::CHILD;
             aEvent.NewValue <<= mxTempAcc;
+            aEvent.IndexHint = getAccessibleChildCount() - 1;
             CommitChange( aEvent );
         }
     }
@@ -2154,6 +2155,7 @@ void ScAccessibleDocument::RemoveChild(const 
uno::Reference<XAccessible>& xAcc,
         aEvent.Source = uno::Reference<XAccessibleContext>(this);
         aEvent.EventId = AccessibleEventId::CHILD;
         aEvent.OldValue <<= mxTempAcc;
+        aEvent.IndexHint = -1;
         CommitChange( aEvent );
     }
     mxTempAcc = nullptr;
diff --git a/vcl/unx/gtk3/a11y/atklistener.cxx 
b/vcl/unx/gtk3/a11y/atklistener.cxx
index b0f091142832..57f40af1db06 100644
--- a/vcl/unx/gtk3/a11y/atklistener.cxx
+++ b/vcl/unx/gtk3/a11y/atklistener.cxx
@@ -171,16 +171,23 @@ void AtkListener::handleChildAdded(
     if( !pChild )
         return;
 
+    bool bNeedToFullFullChildList = true;
     if (nIndexHint != -1)
     {
+        bNeedToFullFullChildList = false;
         sal_Int64 nStateSet = rxParent->getAccessibleStateSet();
         if( !(nStateSet & accessibility::AccessibleStateType::DEFUNC)
               || (nStateSet & 
accessibility::AccessibleStateType::MANAGES_DESCENDANTS) )
         {
             m_aChildList.insert(m_aChildList.begin() + nIndexHint, 
rxAccessible);
+            if (m_aChildList[nIndexHint] != 
rxParent->getAccessibleChild(nIndexHint))
+            {
+                SAL_WARN("vcl", "wrong index hint, falling back to updating 
full child list");
+                bNeedToFullFullChildList = true;
+            }
         }
     }
-    else
+    if (bNeedToFullFullChildList)
         updateChildList(rxParent);
 
     atk_object_wrapper_add_child( mpWrapper, pChild,
@@ -197,20 +204,32 @@ void AtkListener::handleChildRemoved(
     int nChildIndexHint)
 {
     sal_Int32 nIndex = nChildIndexHint;
+    if (nIndex < 0 || nIndex >= static_cast<sal_Int32>(m_aChildList.size()))
+    {
+        SAL_WARN("vcl", "index hint out of range, ignoring");
+        nIndex = -1;
+    }
+    if (nIndex != -1 && rxChild != m_aChildList[nIndex])
+    {
+        SAL_WARN("vcl", "index hint points to wrong child, somebody forgot to 
send accessibility update event");
+        nIndex = -1;
+    }
 
-    // Locate the child in the children list
+    // if the hint did not work, search
     const size_t nmax = m_aChildList.size();
-    for( size_t n = 0; n < nmax; ++n )
-    {
-        // Comparing via uno::Reference::operator== is expensive
-        // with lots of objects, so assume we can find it the cheap way
-        // first, which works most of the time.
-        if( rxChild.get() == m_aChildList[n].get() )
+    if (nIndex == -1)
+        // Locate the child in the children list
+        for( size_t n = 0; n < nmax; ++n )
         {
-            nIndex = n;
-            break;
+            // Comparing via uno::Reference::operator== is expensive
+            // with lots of objects, so assume we can find it the cheap way
+            // first, which works most of the time.
+            if( rxChild.get() == m_aChildList[n].get() )
+            {
+                nIndex = n;
+                break;
+            }
         }
-    }
     // The cheap way failed, find it via the more expensive path
     if (nIndex == -1)
         for( size_t n = 0; n < nmax; ++n )
@@ -248,7 +267,6 @@ void AtkListener::handleChildRemoved(
     if(!( (nStateSet & accessibility::AccessibleStateType::DEFUNC)
         || (nStateSet & 
accessibility::AccessibleStateType::MANAGES_DESCENDANTS) ))
     {
-        assert( m_aChildList[nIndex] == rxParent->getAccessibleChild(nIndex) );
         m_aChildList.erase(m_aChildList.begin() + nIndex);
     }
 

Reply via email to