[Libreoffice-commits] core.git: Branch 'distro/lhm/libreoffice-6-4+backports' - 2 commits - sw/qa sw/source

Michael Stahl (via logerrit) logerrit at kemper.freedesktop.org
Wed Oct 28 07:19:59 UTC 2020


 sw/qa/extras/uiwriter/data/tdf135056.odt |binary
 sw/qa/extras/uiwriter/uiwriter.cxx       |   25 +++++++++++++++
 sw/source/core/layout/fly.cxx            |   49 +++++++++++++++++++++++++++++--
 3 files changed, 72 insertions(+), 2 deletions(-)

New commits:
commit fc67a79cd9268795f8049aea79c8f94d7165de8a
Author:     Michael Stahl <Michael.Stahl at cib.de>
AuthorDate: Thu Oct 22 19:17:24 2020 +0200
Commit:     Michael Stahl <michael.stahl at cib.de>
CommitDate: Wed Oct 28 08:19:36 2020 +0100

    tdf#131679 sw: fix crash when copying fly via context menu
    
    sw::DocumentContentOperationsManager::CopyImplImpl() is called with a
    rPam that's on an SwOLENode.
    
    The problem (which i can't reproduce in --enable-dbgutil build,
    presumably for timing reasons) is that after the context menu pops up,
    some idle layout runs and reformats the document and deletes a
    SwFlyFrame and that calls SdrMarkView::UnmarkAllObj().
    
    Then when SwFEShell::Copy() is called, it finds IsFrameSelected()
    returns false, and it tries to copy normal text when the cursor is on
    an SwOLENode.
    
    Fix this in SwFlyFrame::FinitDrawObj() by first moving the cursor out
    of any selected flys.
    
    (regression from 81ec0039b2085faab49380c7a56af0c562d4c9e4
     - previously CopyImplImpl() would return early)
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104697
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>
    (cherry picked from commit 40bff2567fa4a3fa8ec4445182cbbe3547c17410)
    
    tdf#131679 sw: follow-up: Unmark before SetSelection()
    
    Backporting this to 6.4, it crashes in CppunitTest_desktop_lib because
    some sidebar is loaded from SwView::AttrChangedNotify()/SelectShell()
    and that ends up calling SwView::StateTabWin() about 40 stack frames
    later and this calls SwFEShell::GetAnyCurRect() which gets the still
    selected fly but its page frame is null.
    
    So make sure shells don't see the deleted fly.
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104815
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>
    (cherry picked from commit f63afb95b5c2d80d33a35820ef1d9abd9e70d3ca)
    
    Change-Id: Id135fcc002c03c07c34fbdc0355f2895d8b6565b
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104683
    Tested-by: Michael Stahl <michael.stahl at cib.de>
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>

diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx
index b5f364511f6e..190e799dbc56 100644
--- a/sw/source/core/layout/fly.cxx
+++ b/sw/source/core/layout/fly.cxx
@@ -377,6 +377,32 @@ void SwFlyFrame::InitDrawObj()
                                 : nHellId );
 }
 
+static SwPosition ResolveFlyAnchor(SwFrameFormat const& rFlyFrame)
+{
+    SwFormatAnchor const& rAnch(rFlyFrame.GetAnchor());
+    if (rAnch.GetAnchorId() == RndStdIds::FLY_AT_PAGE)
+    {   // arbitrarily pick last node
+        return SwPosition(SwNodeIndex(rFlyFrame.GetDoc()->GetNodes().GetEndOfContent(), -1));
+    }
+    else
+    {
+        SwPosition const*const pPos(rAnch.GetContentAnchor());
+        assert(pPos);
+        if (SwFrameFormat const*const pParent = pPos->nNode.GetNode().GetFlyFormat())
+        {
+            return ResolveFlyAnchor(*pParent);
+        }
+        else if (pPos->nContent.GetIdxReg())
+        {
+            return *pPos;
+        }
+        else
+        {
+            return SwPosition(*pPos->nNode.GetNode().GetContentNode(), 0);
+        }
+    }
+}
+
 void SwFlyFrame::FinitDrawObj()
 {
     if(!GetVirtDrawObj() )
@@ -391,8 +417,27 @@ void SwFlyFrame::FinitDrawObj()
             for(SwViewShell& rCurrentShell : p1St->GetRingContainer())
             {   // At the moment the Drawing can do just do an Unmark on everything,
                 // as the Object was already removed
-                if(rCurrentShell.HasDrawView() )
-                    rCurrentShell.Imp()->GetDrawView()->UnmarkAll();
+                if (rCurrentShell.HasDrawView() &&
+                    rCurrentShell.Imp()->GetDrawView()->GetMarkedObjectList().GetMarkCount())
+                {
+                    if (SwFEShell *const pFEShell = dynamic_cast<SwFEShell*>(&rCurrentShell))
+                    {   // tdf#131679 move any cursor out of fly
+                        SwFlyFrame const*const pOldSelFly = ::GetFlyFromMarked(nullptr,  pFEShell);
+                        rCurrentShell.Imp()->GetDrawView()->UnmarkAll();
+                        if (pOldSelFly)
+                        {
+                            SwPosition const pos(ResolveFlyAnchor(*pOldSelFly->GetFormat()));
+                            SwPaM const temp(pos);
+                            pFEShell->SetSelection(temp);
+                            // could also call SetCursor() like SwFEShell::SelectObj()
+                            // does, but that would access layout a bit much...
+                        }
+                    }
+                    else
+                    {
+                        rCurrentShell.Imp()->GetDrawView()->UnmarkAll();
+                    }
+                }
             }
         }
     }
commit c64995d1e550b49a226d8f170b2e5533a59bb987
Author:     Xisco Fauli <xiscofauli at libreoffice.org>
AuthorDate: Wed Sep 2 18:35:54 2020 +0200
Commit:     Michael Stahl <michael.stahl at cib.de>
CommitDate: Wed Oct 28 08:19:24 2020 +0100

    tdf#135056: sw_uiwriter: Add unittest
    
    Change-Id: I933537a44b9493adc89516bccb189003cf4f132f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/101950
    Tested-by: Jenkins
    Reviewed-by: Xisco Fauli <xiscofauli at libreoffice.org>
    (cherry picked from commit bc46ff73d6f79d850253f9e1896643eb73238ebb)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104826
    Tested-by: Michael Stahl <michael.stahl at cib.de>
    Reviewed-by: Michael Stahl <michael.stahl at cib.de>

diff --git a/sw/qa/extras/uiwriter/data/tdf135056.odt b/sw/qa/extras/uiwriter/data/tdf135056.odt
new file mode 100644
index 000000000000..bd94317d07d4
Binary files /dev/null and b/sw/qa/extras/uiwriter/data/tdf135056.odt differ
diff --git a/sw/qa/extras/uiwriter/uiwriter.cxx b/sw/qa/extras/uiwriter/uiwriter.cxx
index 0bd769d2b121..b98a12d0e90c 100644
--- a/sw/qa/extras/uiwriter/uiwriter.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter.cxx
@@ -4364,6 +4364,31 @@ void SwUiWriterTest::testDocModState()
     CPPUNIT_ASSERT(!(pShell->IsModified()));
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest, testTdf135056)
+{
+    load(DATA_DIRECTORY, "tdf135056.odt");
+
+    SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
+    CPPUNIT_ASSERT(pTextDoc);
+
+    SwWrtShell* pWrtShell = pTextDoc->GetDocShell()->GetWrtShell();
+    CPPUNIT_ASSERT(pWrtShell);
+
+    CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), pWrtShell->GetTOXCount());
+
+    const SwTOXBase* pTOX = pWrtShell->GetTOX(0);
+    CPPUNIT_ASSERT(pTOX);
+
+    //Without the fix in place, it would have hung here
+    pWrtShell->DeleteTOX(*pTOX, true);
+
+    CPPUNIT_ASSERT_EQUAL(sal_uInt16(0), pWrtShell->GetTOXCount());
+
+    lcl_dispatchCommand(mxComponent, ".uno:Undo", {});
+
+    CPPUNIT_ASSERT_EQUAL(sal_uInt16(1), pWrtShell->GetTOXCount());
+}
+
 void SwUiWriterTest::testTdf94804()
 {
     //create new writer document


More information about the Libreoffice-commits mailing list