sw/source/core/layout/fly.cxx | 43 +++++++++++++++++++++++++++++++++++++++++- 1 file changed, 42 insertions(+), 1 deletion(-)
New commits: commit 40bff2567fa4a3fa8ec4445182cbbe3547c17410 Author: Michael Stahl <[email protected]> AuthorDate: Thu Oct 22 19:17:24 2020 +0200 Commit: Michael Stahl <[email protected]> CommitDate: Fri Oct 23 16:53:55 2020 +0200 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) Change-Id: Id135fcc002c03c07c34fbdc0355f2895d8b6565b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104697 Tested-by: Jenkins Reviewed-by: Michael Stahl <[email protected]> diff --git a/sw/source/core/layout/fly.cxx b/sw/source/core/layout/fly.cxx index d6441aa4679a..1122809daa05 100644 --- a/sw/source/core/layout/fly.cxx +++ b/sw/source/core/layout/fly.cxx @@ -366,6 +366,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() ) @@ -380,8 +406,23 @@ 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() ) + 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); + 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... + } + } rCurrentShell.Imp()->GetDrawView()->UnmarkAll(); + } } } } _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
