[Libreoffice-commits] core.git: 4 commits - sw/source vcl/unx

Michael Stahl mstahl at redhat.com
Mon May 5 15:00:21 PDT 2014


 sw/source/core/access/acctable.cxx |   44 ++++++++++++++++++++++---------------
 sw/source/core/access/acctable.hxx |    9 ++++---
 sw/source/core/layout/tabfrm.cxx   |   22 ------------------
 sw/source/core/undo/untbl.cxx      |   20 +++++++++++-----
 vcl/unx/gtk/a11y/atklistener.cxx   |    5 +++-
 5 files changed, 50 insertions(+), 50 deletions(-)

New commits:
commit d09d75167d77adcc8538c5cc5d8fe6bac6091ca1
Author: Michael Stahl <mstahl at redhat.com>
Date:   Mon May 5 23:33:00 2014 +0200

    AtkListener: consistency check is too strict
    
    Apparently it can happen in JunitTest_sw_unoapi that between the
    getAccessibleChildCount() and the getAccessibleChild() calls that the
    children all disappear; try not to assert in that case.
    
    Change-Id: Iec8e373281950bf684fa76d69f8c4625ecd1255a

diff --git a/vcl/unx/gtk/a11y/atklistener.cxx b/vcl/unx/gtk/a11y/atklistener.cxx
index 3349be8..511ff0a 100644
--- a/vcl/unx/gtk/a11y/atklistener.cxx
+++ b/vcl/unx/gtk/a11y/atklistener.cxx
@@ -137,7 +137,10 @@ void AtkListener::updateChildList(accessibility::XAccessibleContext* pContext)
              }
              catch (lang::IndexOutOfBoundsException const&)
              {
-                 assert(false); // not consistent with getAccessibleChildCount
+                 sal_Int32 nChildren2 = pContext->getAccessibleChildCount();
+                 assert(nChildren2 <= n); // consistency?
+                 m_aChildList.resize(std::min(nChildren2, n));
+                 break;
              }
              OSL_ASSERT(m_aChildList[n].is());
          }
commit f66d9badf9e510f5bbc94201edd5a53c26f8526a
Author: Michael Stahl <mstahl at redhat.com>
Date:   Mon May 5 21:45:55 2014 +0200

    sw: don't dispose SwAccessibles in SwRowFrm::Cut()
    
    This does not appear to work so well: for a row with multiple cells,
    when the second cell frame's SwAccessible is disposed it will send an
    event, and the AtkListener will then request all children of the row,
    and this causes a new SwAccessible to be created for the first cell
    frame that was disposed previously.
    
    Unlike most other events, Dispose events cannot be sent delayed.
    
    The SwAccessibles are disposed from ~SwCellFrm already, that should be
    sufficient.
    
    Change-Id: I6da72605e5386540f8d82535fca151e97d70869f

diff --git a/sw/source/core/access/acctable.cxx b/sw/source/core/access/acctable.cxx
index 2bb9fd6..979dd0d 100644
--- a/sw/source/core/access/acctable.cxx
+++ b/sw/source/core/access/acctable.cxx
@@ -1446,7 +1446,8 @@ void SwAccessibleTable::InvalidateChildPosOrSize( const SwAccessibleChild& rChil
             SwAccessibleTableData_Impl *pNewTableData = CreateNewTableData(); // #i77106#
             if( !pNewTableData->CompareExtents( GetTableData() ) )
             {
-                if(pNewTableData->GetRowCount()!= mpTableData->GetRowCount())
+                if (pNewTableData->GetRowCount() != mpTableData->GetRowCount()
+                    && 1 < GetTableData().GetRowCount())
                 {
                     Int32Set_Impl::const_iterator aSttCol( GetTableData().GetColumnIter( 0 ) );
                     Int32Set_Impl::const_iterator aSttRow( GetTableData().GetRowIter( 1 ) );
diff --git a/sw/source/core/layout/tabfrm.cxx b/sw/source/core/layout/tabfrm.cxx
index 7ac3764..8b26e60 100644
--- a/sw/source/core/layout/tabfrm.cxx
+++ b/sw/source/core/layout/tabfrm.cxx
@@ -4178,28 +4178,6 @@ void SwRowFrm::Cut()
         pTab->FindMaster()->InvalidatePos();
     }
 
-    // #i103961#
-    // notification for accessibility
-    {
-        SwRootFrm *pRootFrm = getRootFrm();
-        if( pRootFrm && pRootFrm->IsAnyShellAccessible() )
-        {
-            SwViewShell* pVSh = pRootFrm->GetCurrShell();
-            if ( pVSh && pVSh->Imp() )
-            {
-                SwFrm* pCellFrm( GetLower() );
-                while ( pCellFrm )
-                {
-                    OSL_ENSURE( pCellFrm->IsCellFrm(),
-                            "<SwRowFrm::Cut()> - unexpected type of SwRowFrm lower." );
-                    pVSh->Imp()->DisposeAccessibleFrm( pCellFrm );
-
-                    pCellFrm = pCellFrm->GetNext();
-                }
-            }
-        }
-    }
-
     SwLayoutFrm::Cut();
 }
 
commit a82de8698a4569d043a3f656a4afbe21a952f8d3
Author: Michael Stahl <mstahl at redhat.com>
Date:   Mon May 5 21:30:43 2014 +0200

    fdo#57197: sw: fix crash on Undo of table row insert on 1-row table
    
    ... with accessibility enabled: the SwCellFrms are deleted, but the
    entry in the SwAccessibleMap::mpFrmMap is not removed, because Dispose
    returns early since the connections to the nodes have been severed already.
    
    This then crashes in some questionable code that iterates over and uses
    the frame pointers in mpFrmMap that was added in
    76c549eb01dcb7b5bf28a271ce00e386f3d388ba (where previously only the
    WeakReferences were used out of that map).
    
    Change-Id: I13885c6ab9a92e34e95925f275e15c20fdc600b7

diff --git a/sw/source/core/undo/untbl.cxx b/sw/source/core/undo/untbl.cxx
index bfdcb55..e1d4833 100644
--- a/sw/source/core/undo/untbl.cxx
+++ b/sw/source/core/undo/untbl.cxx
@@ -1690,6 +1690,7 @@ void SwUndoTblNdsChg::UndoImpl(::sw::UndoRedoContext & rContext)
 
     SwChartDataProvider *pPCD = rDoc.GetChartDataProvider();
     SwSelBoxes aDelBoxes;
+    std::vector< std::pair<SwTableBox *, sal_uLong> > aDelNodes;
     if( IsDelBox() )
     {
         // Trick: add missing boxes in any line, they will be connected
@@ -1754,10 +1755,8 @@ void SwUndoTblNdsChg::UndoImpl(::sw::UndoRedoContext & rContext)
                 rDoc.GetNodes()._MoveNodes( aRg, rDoc.GetNodes(), aInsPos, false );
             }
             else
-            {   // first disconnect box from node, otherwise ~SwTableBox would
-                // access pBox->pSttNd, deleted by DeleteSection
-                pBox->RemoveFromTable();
-                rDoc.DeleteSection( rDoc.GetNodes()[ nIdx ] );
+            {
+                aDelNodes.push_back(std::make_pair(pBox, nIdx));
             }
         }
     }
@@ -1774,8 +1773,7 @@ void SwUndoTblNdsChg::UndoImpl(::sw::UndoRedoContext & rContext)
             if (pPCD)
                 pPCD->DeleteBox( &pTblNd->GetTable(), *pBox );
             aDelBoxes.insert(pBox);
-            pBox->RemoveFromTable(); // ~SwTableBox would access pBox->pSttNd
-            rDoc.DeleteSection( rDoc.GetNodes()[ nIdx ] );
+            aDelNodes.push_back(std::make_pair(pBox, nIdx));
         }
     }
 
@@ -1783,6 +1781,16 @@ void SwUndoTblNdsChg::UndoImpl(::sw::UndoRedoContext & rContext)
     aTmpBox.SetTableLines(aDelBoxes, pTblNd->GetTable());
     aTmpBox.DelFrms(pTblNd->GetTable());
 
+    // do this _after_ deleting Frms because disposing SwAccessible requires
+    // connection to the nodes, see SwAccessibleChild::IsAccessible()
+    for (size_t i = 0; i < aDelNodes.size(); ++i)
+    {
+        // first disconnect box from node, otherwise ~SwTableBox would
+        // access pBox->pSttNd, deleted by DeleteSection
+        aDelNodes[i].first->RemoveFromTable();
+        rDoc.DeleteSection(rDoc.GetNodes()[ aDelNodes[i].second ]);
+    }
+
     // Remove boxes from table structure
     for( sal_uInt16 n = 0; n < aDelBoxes.size(); ++n )
     {
commit cd83ef996b09907d669d686d1a33db5a8f08f72d
Author: Michael Stahl <mstahl at redhat.com>
Date:   Mon May 5 15:23:35 2014 +0200

    fdo#57197: sw: check that cells are still alive ...
    
    ... before firing events from them; use a thread-safe WeakReference.
    
    (regression from 76c549eb01dcb7b5bf28a271ce00e386f3d388ba)
    
    Change-Id: Ie060d27cc44415e9a75b75027f5510577ac17a6e

diff --git a/sw/source/core/access/acctable.cxx b/sw/source/core/access/acctable.cxx
index e798c52..2bb9fd6 100644
--- a/sw/source/core/access/acctable.cxx
+++ b/sw/source/core/access/acctable.cxx
@@ -1730,26 +1730,33 @@ void SwAccessibleTable::FireSelectionEvent( )
 
     aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_REMOVE;
 
-//    int nRemove = m_vecCellRemove.size();
-//    int nAdd = m_vecCellAdd.size();
-
-    VEC_CELL::iterator vi = m_vecCellRemove.begin();
-    for (; vi != m_vecCellRemove.end()  ; ++vi)
+    for (Cells_t::iterator vi = m_vecCellRemove.begin();
+            vi != m_vecCellRemove.end(); ++vi)
     {
-        SwAccessibleContext *pAccCell = const_cast<SwAccessibleContext *>(*vi);
-        OSL_ASSERT(pAccCell != NULL );
-        pAccCell->FireAccessibleEvent(aEvent);
+        // fdo#57197: check if the object is still alive
+        uno::Reference<XAccessible> const xAcc(vi->second);
+        if (xAcc.is())
+        {
+            SwAccessibleContext *const pAccCell(vi->first);
+            assert(pAccCell);
+            pAccCell->FireAccessibleEvent(aEvent);
+        }
     }
 
     if (m_vecCellAdd.size() <= SELECTION_WITH_NUM)
     {
         aEvent.EventId = AccessibleEventId::SELECTION_CHANGED_ADD;
-        vi = m_vecCellAdd.begin();
-        for (; vi != m_vecCellAdd.end()  ; ++vi)
+        for (Cells_t::iterator vi = m_vecCellAdd.begin();
+                vi != m_vecCellAdd.end(); ++vi)
         {
-            SwAccessibleContext *pAccCell = const_cast<SwAccessibleContext *>(*vi);
-            OSL_ASSERT(pAccCell != NULL );
-            pAccCell->FireAccessibleEvent(aEvent);
+            // fdo#57197: check if the object is still alive
+            uno::Reference<XAccessible> const xAcc(vi->second);
+            if (xAcc.is())
+            {
+                SwAccessibleContext *const pAccCell(vi->first);
+                assert(pAccCell);
+                pAccCell->FireAccessibleEvent(aEvent);
+            }
         }
         return ;
     }
@@ -1760,15 +1767,17 @@ void SwAccessibleTable::FireSelectionEvent( )
     }
 }
 
-void SwAccessibleTable::AddSelectionCell(const SwAccessibleContext* pAccCell, bool bAddOrRemove)
+void SwAccessibleTable::AddSelectionCell(
+        SwAccessibleContext *const pAccCell, bool const bAddOrRemove)
 {
+    uno::Reference<XAccessible> const xTmp(pAccCell);
     if (bAddOrRemove)
     {
-        m_vecCellAdd.push_back(pAccCell);
+        m_vecCellAdd.push_back(std::make_pair(pAccCell, xTmp));
     }
     else
     {
-        m_vecCellRemove.push_back(pAccCell);
+        m_vecCellRemove.push_back(std::make_pair(pAccCell, xTmp));
     }
 }
 
diff --git a/sw/source/core/access/acctable.hxx b/sw/source/core/access/acctable.hxx
index 88f5916..2bbd14f 100644
--- a/sw/source/core/access/acctable.hxx
+++ b/sw/source/core/access/acctable.hxx
@@ -266,11 +266,12 @@ public:
     // XAccessibleComponent
     sal_Int32 SAL_CALL getBackground()
         throw (::com::sun::star::uno::RuntimeException, std::exception) SAL_OVERRIDE;
-    typedef std::vector<const SwAccessibleContext*> VEC_CELL;
-    VEC_CELL m_vecCellAdd;
-    VEC_CELL m_vecCellRemove;
+    typedef std::vector< ::std::pair<SwAccessibleContext*,
+        css::uno::WeakReference<css::accessibility::XAccessible> > > Cells_t;
+    Cells_t m_vecCellAdd;
+    Cells_t m_vecCellRemove;
     void FireSelectionEvent( );
-    void AddSelectionCell(const SwAccessibleContext* , bool bAddOrRemove);
+    void AddSelectionCell(SwAccessibleContext*, bool bAddOrRemove);
 };
 
 inline SwAccessibleTableData_Impl& SwAccessibleTable::GetTableData()


More information about the Libreoffice-commits mailing list