summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJim Raykowski <raykowj@gmail.com>2021-12-28 23:03:59 -0900
committerAdolfo Jayme Barrientos <fitojb@ubuntu.com>2022-01-05 15:56:58 +0100
commit0b592cad64d02cb3e7f4da73c129ccd4d939d93e (patch)
tree1e252de01f60f73147e42e3cdc2e505735f28f90
parentf48c82cc5c2fcff4c8b6848daf66be61fd04d374 (diff)
Outline folding: Check frame area is valid before using pointer to
saved outline frame It seems when a frame is removed it is not immediately destroyed, so a pointer to the removed frame may not be a null pointer. This patch checks for valid frame area definition before using the save outline frame pointer with intention to fix an intermittent crash occurrence when an outline paragraph is removed. Change-Id: I4f9b55acc6aeb83553a3f26c2701159c2ba439a2 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127717 Tested-by: Jenkins Reviewed-by: Jim Raykowski <raykowj@gmail.com> Signed-off-by: Xisco Fauli <xiscofauli@libreoffice.org> Reviewed-on: https://gerrit.libreoffice.org/c/core/+/127933 Reviewed-by: Adolfo Jayme Barrientos <fitojb@ubuntu.com>
-rw-r--r--sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx3
-rw-r--r--sw/source/uibase/docvw/edtwin.cxx77
-rw-r--r--sw/source/uibase/inc/edtwin.hxx7
3 files changed, 56 insertions, 31 deletions
diff --git a/sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx b/sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx
index 0253e8a93023..3e16a5e0997f 100644
--- a/sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx
+++ b/sw/source/uibase/docvw/OutlineContentVisibilityWin.cxx
@@ -211,7 +211,8 @@ IMPL_LINK(SwOutlineContentVisibilityWin, MouseMoveHdl, const MouseEvent&, rMEvt,
// for saved outline frame is now disposed.
}
}
- GetEditWin()->SetSavedOutlineFrame(const_cast<SwFrame*>(GetFrame()));
+ GetEditWin()->SetSavedOutlineFrame(
+ static_cast<SwTextFrame*>(const_cast<SwFrame*>(GetFrame())));
}
if (!m_bDestroyed && m_aDelayTimer.IsActive())
m_aDelayTimer.Stop();
diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx
index b3bdb09dcff4..e4791daff6a0 100644
--- a/sw/source/uibase/docvw/edtwin.cxx
+++ b/sw/source/uibase/docvw/edtwin.cxx
@@ -3888,40 +3888,56 @@ void SwEditWin::MouseMove(const MouseEvent& _rMEvt)
SwContentAtPos aSwContentAtPos(IsAttrAtPos::Outline);
if (rSh.GetContentAtPos(PixelToLogic(rMEvt.GetPosPixel()), aSwContentAtPos))
{
+ // mouse pointer is on an outline paragraph node
if(aSwContentAtPos.aFnd.pNode && aSwContentAtPos.aFnd.pNode->IsTextNode())
{
- SwContentFrame* pContentFrame = aSwContentAtPos.aFnd.pNode->GetTextNode()->getLayoutFrame(nullptr);
+ // Get the outline paragraph frame and compare it to the saved ouline frame. If they
+ // are not the same, remove the fold button from the saved outline frame, if not
+ // already removed, and then add a fold button to the mouse over outline frame if
+ // the content is not folded.
+ SwContentFrame* pContentFrame =
+ aSwContentAtPos.aFnd.pNode->GetTextNode()->getLayoutFrame(rSh.GetLayout());
if (pContentFrame != m_pSavedOutlineFrame)
{
- if (m_pSavedOutlineFrame && !m_pSavedOutlineFrame->IsInDtor())
+ if (m_pSavedOutlineFrame)
{
- SwTextNode* pTextNode =
- static_cast<SwTextFrame*>(m_pSavedOutlineFrame)->GetTextNodeFirst();
- if (pTextNode && rNds.GetOutLineNds().Seek_Entry(pTextNode, &nPos) &&
- rSh.GetAttrOutlineContentVisible(nPos))
- GetFrameControlsManager().RemoveControlsByType(
- FrameControlType::Outline, m_pSavedOutlineFrame);
+ if (m_pSavedOutlineFrame->isFrameAreaDefinitionValid())
+ {
+ SwTextNode* pTextNode = m_pSavedOutlineFrame->GetTextNodeFirst();
+ if (pTextNode && rNds.GetOutLineNds().Seek_Entry(pTextNode, &nPos) &&
+ rSh.GetAttrOutlineContentVisible(nPos))
+ {
+ GetFrameControlsManager().RemoveControlsByType(
+ FrameControlType::Outline, m_pSavedOutlineFrame);
+ }
+ }
}
- m_pSavedOutlineFrame = pContentFrame;
+ m_pSavedOutlineFrame = static_cast<SwTextFrame*>(pContentFrame);
}
- // show button
+ // show fold button if outline content is visible
if (rNds.GetOutLineNds().Seek_Entry(aSwContentAtPos.aFnd.pNode->GetTextNode(), &nPos) &&
rSh.GetAttrOutlineContentVisible(nPos))
GetFrameControlsManager().SetOutlineContentVisibilityButton(pContentFrame);
}
}
- else if (m_pSavedOutlineFrame && !m_pSavedOutlineFrame->IsInDtor())
+ else if (m_pSavedOutlineFrame)
{
- // current pointer pos is not over an outline frame
- // previous pointer pos was over an outline frame
- // remove outline content visibility button if showing
- if (m_pSavedOutlineFrame->isFrameAreaDefinitionValid() &&
- m_pSavedOutlineFrame->IsTextFrame() &&
- rNds.GetOutLineNds().Seek_Entry(
- static_cast<SwTextFrame*>(m_pSavedOutlineFrame)->GetTextNodeFirst(), &nPos)
- && rSh.GetAttrOutlineContentVisible(nPos))
- GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline,
- m_pSavedOutlineFrame);
+ // The saved frame may not still be in the document, e.g., when an outline paragraph
+ // is deleted. This causes the call to GetTextNodeFirst to behave badly. Use
+ // isFrameAreaDefinitionValid to check if the frame is still in the document.
+ if (m_pSavedOutlineFrame->isFrameAreaDefinitionValid())
+ {
+ // current pointer pos is not over an outline frame
+ // previous pointer pos was over an outline frame
+ // remove outline content visibility button if showing
+ SwTextNode* pTextNode = m_pSavedOutlineFrame->GetTextNodeFirst();
+ if (pTextNode && rNds.GetOutLineNds().Seek_Entry(pTextNode, &nPos) &&
+ rSh.GetAttrOutlineContentVisible(nPos))
+ {
+ GetFrameControlsManager().RemoveControlsByType(
+ FrameControlType::Outline, m_pSavedOutlineFrame);
+ }
+ }
m_pSavedOutlineFrame = nullptr;
}
}
@@ -3964,13 +3980,20 @@ void SwEditWin::MouseMove(const MouseEvent& _rMEvt)
{
if (m_pSavedOutlineFrame && !bInsWin)
{
- // the mouse pointer has left the building
+ // the mouse pointer has left the building (edit window)
// remove the outline content visibility button if showing
- const SwNodes& rNds = rSh.GetDoc()->GetNodes();
- SwOutlineNodes::size_type nPos;
- if (rNds.GetOutLineNds().Seek_Entry(static_cast<SwTextFrame*>(m_pSavedOutlineFrame)->GetTextNodeFirst(), &nPos) &&
- rSh.GetAttrOutlineContentVisible(nPos))
- GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline, m_pSavedOutlineFrame);
+ if (m_pSavedOutlineFrame->isFrameAreaDefinitionValid())
+ {
+ const SwNodes& rNds = rSh.GetDoc()->GetNodes();
+ SwOutlineNodes::size_type nPos;
+ SwTextNode* pTextNode = m_pSavedOutlineFrame->GetTextNodeFirst();
+ if (pTextNode && rNds.GetOutLineNds().Seek_Entry(pTextNode, &nPos) &&
+ rSh.GetAttrOutlineContentVisible(nPos))
+ {
+ GetFrameControlsManager().RemoveControlsByType(FrameControlType::Outline,
+ m_pSavedOutlineFrame);
+ }
+ }
m_pSavedOutlineFrame = nullptr;
}
}
diff --git a/sw/source/uibase/inc/edtwin.hxx b/sw/source/uibase/inc/edtwin.hxx
index 06fbee57f0e3..a88e75c7bdec 100644
--- a/sw/source/uibase/inc/edtwin.hxx
+++ b/sw/source/uibase/inc/edtwin.hxx
@@ -45,6 +45,7 @@ struct QuickHelpData;
class SdrDropMarkerOverlay;
class SwFrameControlsManager;
enum class SdrHitKind;
+class SwTextFrame;
// input window
@@ -127,7 +128,7 @@ class SW_DLLPUBLIC SwEditWin final : public vcl::Window,
std::unique_ptr<SwFrameControlsManager> m_pFrameControlsManager;
- SwFrame* m_pSavedOutlineFrame = nullptr;
+ SwTextFrame* m_pSavedOutlineFrame = nullptr;
void LeaveArea(const Point &);
void JustifyAreaTimer();
@@ -291,8 +292,8 @@ public:
/// Allows starting or ending a graphic move or resize action.
void SetGraphicTwipPosition(bool bStart, const Point& rPosition);
- const SwFrame* GetSavedOutlineFrame() const { return m_pSavedOutlineFrame; }
- void SetSavedOutlineFrame(SwFrame* pFrame) { m_pSavedOutlineFrame = pFrame; }
+ const SwTextFrame* GetSavedOutlineFrame() const { return m_pSavedOutlineFrame; }
+ void SetSavedOutlineFrame(SwTextFrame* pFrame) { m_pSavedOutlineFrame = pFrame; }
void ToggleOutlineContentVisibility(const size_t nOutlinePos, const bool bSubs);
virtual FactoryFunction GetUITestFactory() const override;