summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Stahl <Michael.Stahl@cib.de>2020-10-22 19:17:24 +0200
committerAndras Timar <andras.timar@collabora.com>2020-10-31 22:54:57 +0100
commitf7f1dee0a5e016a61bf6d36a6a6b758d81ec6fa6 (patch)
tree815b7fed5e51f91cc82cb4c00d9f34792084108b
parent9af45cc8f109a70b5314202303daa42a425b11be (diff)
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@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@cib.de> (cherry picked from commit f63afb95b5c2d80d33a35820ef1d9abd9e70d3ca) Change-Id: Id135fcc002c03c07c34fbdc0355f2895d8b6565b Reviewed-on: https://gerrit.libreoffice.org/c/core/+/104682 Tested-by: Jenkins Reviewed-by: Caolán McNamara <caolanm@redhat.com> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105095 Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com> Reviewed-by: Andras Timar <andras.timar@collabora.com>
-rw-r--r--sw/source/core/layout/fly.cxx49
1 files changed, 47 insertions, 2 deletions
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();
+ }
+ }
}
}
}