sw/inc/anchoredobject.hxx              |    5 +
 sw/qa/extras/layout/data/tdf148897.odt |binary
 sw/qa/extras/layout/layout2.cxx        |   82 +++++++++++++++++++++++++++
 sw/source/core/inc/txtfly.hxx          |    4 +
 sw/source/core/inc/txtfrm.hxx          |    3 
 sw/source/core/layout/flylay.cxx       |    2 
 sw/source/core/layout/frmtool.cxx      |    5 +
 sw/source/core/layout/layact.cxx       |    6 +
 sw/source/core/text/frmform.cxx        |  100 +++++++++++++++++++++++++++++++--
 sw/source/core/text/txtfly.cxx         |   29 +++++----
 sw/source/core/view/viewsh.cxx         |    3 
 11 files changed, 219 insertions(+), 20 deletions(-)

New commits:
commit b0e2b60fa45f236f6a993cc1295a7afddabb5098
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Wed May 24 20:16:49 2023 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed May 24 22:29:15 2023 +0200

    tdf#148897 tdf#143239 sw: move flys off the page in SwTextFrame::Format()
    
    The bugfix regresses testTdf143239, so we add some scary additional hacks:
    
    * testTdf143239: turns out that this was already moving back and forth
      many times but then ran into some loop control - now with the fix for
      tdf#148897 this still happens, but the result is now bad, where
      previously it was good (by accident?).
    
      Move the flys off the page also in SwTextFrame::Format() - there is
      already code there to detect that footnotes have been moved off by
      Format_() - this is similar, the formatting should be redone immediately
      if there is a fly that created SwFlyPortions in the current frame, but
      the fly was actually moved to the next page by the very same
      Format_() splitting the frame.
    
    * testKeepWithNextPlusFlyFollowTextFlow: here the problem was that the
      para with the fly didn't move back to page 1; need to clear the
      SwLayouter when toggling FieldNames.
    
    * testKeepwithnextFullheight: this test document will loop creating
      infinite pages if the newly add move code is run during
      SwObjectFormatterTextFrame - the latter must move the flys if it is
      active, not SwTextFrame::Format().
    
    This is all a bit experimental but i failed to have a better idea...
    
    (regression from previous commit)
    
    Change-Id: Icfcbd270137116198128d549b34e7f49a47b6911
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152246
    Tested-by: Jenkins
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sw/source/core/inc/txtfly.hxx b/sw/source/core/inc/txtfly.hxx
index 37d78e3c822f..95d70198f858 100644
--- a/sw/source/core/inc/txtfly.hxx
+++ b/sw/source/core/inc/txtfly.hxx
@@ -152,7 +152,9 @@ class SwTextFly
 
     SwAnchoredObjList* InitAnchoredObjList();
 
+public:
     SwAnchoredObjList* GetAnchoredObjList() const;
+private:
 
     /**
         Look for the first object which overlaps with the rectangle.
@@ -302,6 +304,8 @@ public:
     void SetIgnoreContour( bool bNew );
 
     void SetIgnoreObjsInHeaderFooter( const bool bNew );
+
+    SwRect GetFrameArea() const;
 };
 
 inline SwAnchoredObjList* SwTextFly::GetAnchoredObjList() const
diff --git a/sw/source/core/inc/txtfrm.hxx b/sw/source/core/inc/txtfrm.hxx
index 2376153b40d3..c4c51503ec98 100644
--- a/sw/source/core/inc/txtfrm.hxx
+++ b/sw/source/core/inc/txtfrm.hxx
@@ -268,7 +268,8 @@ class SW_DLLPUBLIC SwTextFrame final : public SwContentFrame
 
     // In order to safe stack space, we split this method:
     // Format_ calls Format_ with parameters
-    void Format_( vcl::RenderContext* pRenderContext, SwParaPortion *pPara );
+    void FormatImpl( vcl::RenderContext* pRenderContext, SwParaPortion *pPara,
+            ::std::vector<SwAnchoredObject *> & rIntersectingObjs);
     void Format_( SwTextFormatter &rLine, SwTextFormatInfo &rInf,
                   const bool bAdjust = false );
     void FormatOnceMore( SwTextFormatter &rLine, SwTextFormatInfo &rInf );
diff --git a/sw/source/core/text/frmform.cxx b/sw/source/core/text/frmform.cxx
index 912047487a64..5fdf320d4eee 100644
--- a/sw/source/core/text/frmform.cxx
+++ b/sw/source/core/text/frmform.cxx
@@ -50,6 +50,8 @@
 #include <redline.hxx>
 #include <comphelper/lok.hxx>
 #include <flyfrms.hxx>
+#include <frmtool.hxx>
+#include <layouter.hxx>
 
 // Tolerance in formatting and text output
 #define SLOPPY_TWIPS    5
@@ -1775,7 +1777,8 @@ void SwTextFrame::FormatOnceMore( SwTextFormatter &rLine, 
SwTextFormatInfo &rInf
     }
 }
 
-void SwTextFrame::Format_( vcl::RenderContext* pRenderContext, SwParaPortion 
*pPara )
+void SwTextFrame::FormatImpl(vcl::RenderContext* pRenderContext, SwParaPortion 
*pPara,
+        std::vector<SwAnchoredObject *> & rIntersectingObjs)
 {
     const bool bIsEmpty = GetText().isEmpty();
 
@@ -1810,6 +1813,18 @@ void SwTextFrame::Format_( vcl::RenderContext* 
pRenderContext, SwParaPortion *pP
     if( aLine.IsOnceMore() )
         FormatOnceMore( aLine, aInf );
 
+    if (aInf.GetTextFly().IsOn())
+    {
+        SwRect const aRect(aInf.GetTextFly().GetFrameArea());
+        for (SwAnchoredObject *const pObj : 
*aInf.GetTextFly().GetAnchoredObjList())
+        {
+            if (!aInf.GetTextFly().AnchoredObjToRect(pObj, aRect).IsEmpty())
+            {
+                rIntersectingObjs.push_back(pObj);
+            }
+        }
+    }
+
     if ( IsVertical() )
         SwapWidthAndHeight();
 
@@ -1991,7 +2006,13 @@ void SwTextFrame::Format( vcl::RenderContext* 
pRenderContext, const SwBorderAttr
             }
             do
             {
-                Format_( pRenderContext, aAccess.GetPara() );
+                ::std::vector<SwAnchoredObject *> intersectingObjs;
+                ::std::vector<SwFrame const*> nexts;
+                for (SwFrame const* pNext = GetNext(); pNext; pNext = 
pNext->GetNext())
+                {
+                    nexts.push_back(pNext);
+                }
+                FormatImpl(pRenderContext, aAccess.GetPara(), 
intersectingObjs);
                 if( pFootnoteBoss && nFootnoteHeight )
                 {
                     const SwFootnoteContFrame* pCont = 
pFootnoteBoss->FindFootnoteCont();
@@ -1999,12 +2020,79 @@ void SwTextFrame::Format( vcl::RenderContext* 
pRenderContext, const SwBorderAttr
                     // If we lost some footnotes, we may have more space
                     // for our main text, so we have to format again ...
                     if( nNewHeight < nFootnoteHeight )
+                    {
                         nFootnoteHeight = nNewHeight;
-                    else
-                        break;
+                        continue;
+                    }
                 }
-                else
-                    break;
+                if (!intersectingObjs.empty())
+                {
+                    // assumption is that FormatImpl() only moves frames
+                    // in the next-chain to next page
+                    SwPageFrame *const pPage(FindPageFrame());
+                    SwTextFrame * pLastMovedAnchor(nullptr);
+                    auto lastIter(nexts.end());
+                    for (SwAnchoredObject *const pObj : intersectingObjs)
+                    {
+                        SwFrame *const pAnchor(pObj->AnchorFrame());
+                        SwPageFrame *const 
pAnchorPage(pAnchor->FindPageFrame());
+                        if (pAnchorPage != pPage)
+                        {
+                            auto const iter(::std::find(nexts.begin(), 
nexts.end(), pAnchor));
+                            if (iter != nexts.end())
+                            {
+                                assert(pAnchor->IsTextFrame());
+                                // (can't check SwOszControl::IsInProgress()?)
+                                // called in loop in 
FormatAnchorFrameAndItsPrevs()
+                                if (static_cast<SwTextFrame 
const*>(pAnchor)->IsJoinLocked()
+                                    // called in loop in SwFrame::PrepareMake()
+                                    || pAnchor->IsDeleteForbidden())
+                                {
+                                    // when called via 
FormatAnchorFrameAndItsPrevs():
+                                    // don't do anything, caller will handle it
+                                    pLastMovedAnchor = nullptr;
+                                    break;
+                                }
+                                assert(pPage->GetPhyPageNum() < 
pAnchorPage->GetPhyPageNum()); // how could it move backward?
+
+                                if (!pLastMovedAnchor || iter < lastIter)
+                                {
+                                    pLastMovedAnchor = static_cast<SwTextFrame 
*>(pAnchor);
+                                    lastIter = iter;
+                                }
+                            }
+                        }
+                    }
+                    SwPageFrame const*const pPrevPage(static_cast<SwPageFrame 
const*>(pPage->GetPrev()));
+                    if (pLastMovedAnchor)
+                    {
+                        for (SwAnchoredObject *const pObj : intersectingObjs)
+                        {
+                            if (pObj->AnchorFrame() == pLastMovedAnchor)
+                            {
+                                SwPageFrame *const 
pAnchorPage(pLastMovedAnchor->FindPageFrame());
+                                SAL_INFO("sw.layout", "SwTextFrame::Format: 
move anchored " << pObj << " from " << pPage->GetPhyPageNum() << " to " << 
pAnchorPage->GetPhyPageNum());
+                                pObj->RegisterAtPage(*pAnchorPage);
+                                // tdf#143239 if the position remains valid, 
it may not be
+                                // positioned again so would remain on the 
wrong page!
+                                pObj->InvalidateObjPos();
+                                ::Notify_Background(pObj->GetDrawObj(), pPage,
+                                    pObj->GetObjRect(), 
PrepareHint::FlyFrameLeave, false);
+                                pObj->SetForceNotifyNewBackground(true);
+                            }
+                        }
+                        if (GetFollow() // this frame was split
+                            && (!pPrevPage // prev page is still valid
+                                || (!pPrevPage->IsInvalid()
+                                    && (!pPrevPage->GetSortedObjs() || 
!pPrevPage->IsInvalidFly()))))
+                        {   // this seems a bit risky...
+                            
SwLayouter::InsertMovedFwdFrame(GetTextNodeFirst()->GetDoc(),
+                                *pLastMovedAnchor, 
FindPageFrame()->GetPhyPageNum() + 1);
+                        }
+                        continue; // try again without the fly
+                    }
+                }
+                break;
             } while ( pFootnoteBoss );
             if( bOrphan )
             {
diff --git a/sw/source/core/text/txtfly.cxx b/sw/source/core/text/txtfly.cxx
index 2c7f5aeadb4f..cb5105763e73 100644
--- a/sw/source/core/text/txtfly.cxx
+++ b/sw/source/core/text/txtfly.cxx
@@ -823,6 +823,22 @@ bool SwTextFly::GetTop( const SwAnchoredObject* 
_pAnchoredObj,
     return false;
 }
 
+SwRect SwTextFly::GetFrameArea() const
+{
+    // i#28701 - consider complete frame area for new text wrapping
+    SwRect aRect;
+    if 
(m_pCurrFrame->GetDoc().getIDocumentSettingAccess().get(DocumentSettingId::USE_FORMER_TEXT_WRAPPING))
+    {
+        aRect = m_pCurrFrame->getFramePrintArea();
+        aRect += m_pCurrFrame->getFrameArea().Pos();
+    }
+    else
+    {
+        aRect = m_pCurrFrame->getFrameArea();
+    }
+    return aRect;
+}
+
 // #i68520#
 SwAnchoredObjList* SwTextFly::InitAnchoredObjList()
 {
@@ -853,18 +869,7 @@ SwAnchoredObjList* SwTextFly::InitAnchoredObjList()
         // #i68520#
         mpAnchoredObjList.reset(new SwAnchoredObjList );
 
-        // #i28701# - consider complete frame area for new
-        // text wrapping
-        SwRect aRect;
-        if ( pIDSA->get(DocumentSettingId::USE_FORMER_TEXT_WRAPPING) )
-        {
-            aRect = m_pCurrFrame->getFramePrintArea();
-            aRect += m_pCurrFrame->getFrameArea().Pos();
-        }
-        else
-        {
-            aRect = m_pCurrFrame->getFrameArea();
-        }
+        SwRect const aRect(GetFrameArea());
         // Make ourselves a little smaller than we are,
         // so that 1-Twip-overlappings are ignored (#49532)
         SwRectFnSet aRectFnSet(m_pCurrFrame);
diff --git a/sw/source/core/view/viewsh.cxx b/sw/source/core/view/viewsh.cxx
index e501545e7396..b514990bfed3 100644
--- a/sw/source/core/view/viewsh.cxx
+++ b/sw/source/core/view/viewsh.cxx
@@ -66,6 +66,7 @@
 #include <anchoredobject.hxx>
 #include <DocumentSettingManager.hxx>
 #include <DocumentRedlineManager.hxx>
+#include <DocumentLayoutManager.hxx>
 
 #include <unotxdoc.hxx>
 #include <view.hxx>
@@ -2425,6 +2426,8 @@ void SwViewShell::ImplApplyViewOptions( const 
SwViewOption &rOpt )
                 }
             }
         }
+        // the layout changes but SetModified() wasn't called so do it here:
+        mxDoc->GetDocumentLayoutManager().ClearSwLayouterEntries();
     }
 
     if( !bOnlineSpellChgd )
commit 35f7f1ad9c2aba1644a46dfb4da0a86f72c6a224
Author:     Michael Stahl <michael.st...@allotropia.de>
AuthorDate: Wed May 24 19:50:16 2023 +0200
Commit:     Michael Stahl <michael.st...@allotropia.de>
CommitDate: Wed May 24 22:29:09 2023 +0200

    tdf#148897 sw: layout: force invalidate background when moving fly off page
    
    The fly 15 moves forward in SwLayAction::FormatContent(), then back
    again later, without being positioned on the next page, and it happens
    to go to the same position that it originally had.
    
    Then SwFlyNotify sees that the position is the same, and doesn't do any
    invalidation of the background, so the fly overlaps a text frame.
    
    When the fly is moved by the object positioning code (before the below
    commit), it first gets a new position on the next page, and then moves
    back, so all invalidations happen.
    
    Force the invalidation of the background in this case.
    
    (regression from commit eb85de8e6b61fb3fcb6c03ae0145f7fe5478bccf
     "sw: layout: if fly's anchor moves forward, move fly off SwPageFrame")
    
    Change-Id: Ifdc9460defe7b1f37cbb05310906146919e8fb6a
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/152245
    Tested-by: Michael Stahl <michael.st...@allotropia.de>
    Reviewed-by: Michael Stahl <michael.st...@allotropia.de>

diff --git a/sw/inc/anchoredobject.hxx b/sw/inc/anchoredobject.hxx
index ea8104882b4d..19cd2e75802b 100644
--- a/sw/inc/anchoredobject.hxx
+++ b/sw/inc/anchoredobject.hxx
@@ -109,6 +109,8 @@ class SW_DLLPUBLIC SwAnchoredObject
         // page frame starts.
         bool mbTmpConsiderWrapInfluence;
 
+        bool mbForceNotifyNewBackground = false;
+
         mutable SwRect maObjRectWithSpaces;
         mutable bool mbObjRectWithSpacesValid;
         mutable SwRect maLastObjRect;
@@ -423,6 +425,9 @@ class SW_DLLPUBLIC SwAnchoredObject
         bool IsTmpConsiderWrapInfluence() const { return 
mbTmpConsiderWrapInfluence;}
         void ClearTmpConsiderWrapInfluence();
 
+        bool IsForceNotifyNewBackground() { return mbForceNotifyNewBackground; 
}
+        void SetForceNotifyNewBackground(bool const b) { 
mbForceNotifyNewBackground = b; }
+
         /** method to determine, if the anchored object is overlapping with a
             previous column
 
diff --git a/sw/qa/extras/layout/data/tdf148897.odt 
b/sw/qa/extras/layout/data/tdf148897.odt
new file mode 100644
index 000000000000..d5d1555c9976
Binary files /dev/null and b/sw/qa/extras/layout/data/tdf148897.odt differ
diff --git a/sw/qa/extras/layout/layout2.cxx b/sw/qa/extras/layout/layout2.cxx
index 3f8045804e24..b4b004951bf0 100644
--- a/sw/qa/extras/layout/layout2.cxx
+++ b/sw/qa/extras/layout/layout2.cxx
@@ -12,6 +12,7 @@
 #include <com/sun/star/text/XTextFrame.hpp>
 #include <com/sun/star/text/XTextTable.hpp>
 #include <com/sun/star/linguistic2/XHyphenator.hpp>
+#include <com/sun/star/view/XSelectionSupplier.hpp>
 
 #include <comphelper/scopeguard.hxx>
 #include <comphelper/sequence.hxx>
@@ -144,6 +145,87 @@ CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, 
testTdf100680_as_char_wrap)
     // If the third line missing that assert will fire, as was before the fix.
 }
 
+CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testTdf148897)
+{
+    createSwDoc("tdf148897.odt");
+
+    xmlDocUniquePtr pXmlDoc = parseLayoutDump();
+
+    assertXPath(pXmlDoc, "/root/page[1]/sorted_objs/fly", 1);
+    assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/anchored/fly", 1);
+    assertXPath(pXmlDoc, "/root/page[2]/sorted_objs/fly", 1);
+    assertXPath(pXmlDoc, "/root/page[2]/body/txt[3]/anchored/fly", 1);
+    assertXPath(pXmlDoc, "/root/page[3]/sorted_objs/fly", 0);
+    assertXPath(pXmlDoc, "/root/page[3]/body/txt/anchored/fly", 0);
+    assertXPath(pXmlDoc, "/root/page[4]/sorted_objs/fly", 1);
+    assertXPath(pXmlDoc, "/root/page[4]/body/txt[1]/anchored/fly", 1);
+    // fly portion exists, no overlapping text
+    assertXPath(pXmlDoc, 
"/root/page[4]/body/txt[1]/SwParaPortion/SwLineLayout[1]/SwFixPortion",
+                "height", "5797");
+    assertXPath(pXmlDoc, "/root/page[5]/sorted_objs/fly", 0);
+    assertXPath(pXmlDoc, "/root/page", 5);
+
+    auto xModel = mxComponent.queryThrow<frame::XModel>();
+    uno::Reference<drawing::XShape> xShape(getShapeByName(u"Image3"));
+    uno::Reference<view::XSelectionSupplier> 
xCtrl(xModel->getCurrentController(), uno::UNO_QUERY);
+    xCtrl->select(uno::Any(xShape));
+
+    dispatchCommand(mxComponent, ".uno:Delete", {});
+
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+
+    assertXPath(pXmlDoc, "/root/page[1]/sorted_objs/fly", 0);
+    assertXPath(pXmlDoc, "/root/page[1]/body/txt/anchored/fly", 0);
+    assertXPath(pXmlDoc, "/root/page[2]/sorted_objs/fly", 1);
+    assertXPath(pXmlDoc, "/root/page[2]/body/txt[1]/anchored/fly", 1);
+    assertXPath(pXmlDoc, "/root/page[3]/sorted_objs/fly", 1);
+    assertXPath(pXmlDoc, "/root/page[3]/body/txt[2]/anchored/fly", 1);
+    // fly portion exists, no overlapping text
+    assertXPath(pXmlDoc, 
"/root/page[3]/body/txt[1]/SwParaPortion/SwLineLayout[1]/SwFixPortion",
+                "height", "5797");
+    assertXPath(pXmlDoc, "/root/page[4]/sorted_objs/fly", 0);
+    assertXPath(pXmlDoc, "/root/page[4]/body/txt/anchored/fly", 0);
+    assertXPath(pXmlDoc, "/root/page", 4);
+
+    dispatchCommand(mxComponent, ".uno:Undo", {});
+
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+
+    assertXPath(pXmlDoc, "/root/page[1]/sorted_objs/fly", 1);
+    assertXPath(pXmlDoc, "/root/page[1]/body/txt[2]/anchored/fly", 1);
+    assertXPath(pXmlDoc, "/root/page[2]/sorted_objs/fly", 1);
+    assertXPath(pXmlDoc, "/root/page[2]/body/txt[3]/anchored/fly", 1);
+    assertXPath(pXmlDoc, "/root/page[3]/sorted_objs/fly", 0);
+    assertXPath(pXmlDoc, "/root/page[3]/body/txt/anchored/fly", 0);
+    assertXPath(pXmlDoc, "/root/page[4]/sorted_objs/fly", 1);
+    assertXPath(pXmlDoc, "/root/page[4]/body/txt[1]/anchored/fly", 1);
+    // fly portion exists, no overlapping text
+    assertXPath(pXmlDoc, 
"/root/page[4]/body/txt[1]/SwParaPortion/SwLineLayout[1]/SwFixPortion",
+                "height", "5797");
+    assertXPath(pXmlDoc, "/root/page[5]/sorted_objs/fly", 0);
+    assertXPath(pXmlDoc, "/root/page", 5);
+
+    dispatchCommand(mxComponent, ".uno:Redo", {});
+
+    discardDumpedLayout();
+    pXmlDoc = parseLayoutDump();
+
+    assertXPath(pXmlDoc, "/root/page[1]/sorted_objs/fly", 0);
+    assertXPath(pXmlDoc, "/root/page[1]/body/txt/anchored/fly", 0);
+    assertXPath(pXmlDoc, "/root/page[2]/sorted_objs/fly", 1);
+    assertXPath(pXmlDoc, "/root/page[2]/body/txt[1]/anchored/fly", 1);
+    assertXPath(pXmlDoc, "/root/page[3]/sorted_objs/fly", 1);
+    assertXPath(pXmlDoc, "/root/page[3]/body/txt[2]/anchored/fly", 1);
+    // fly portion exists, no overlapping text
+    assertXPath(pXmlDoc, 
"/root/page[3]/body/txt[1]/SwParaPortion/SwLineLayout[1]/SwFixPortion",
+                "height", "5797");
+    assertXPath(pXmlDoc, "/root/page[4]/sorted_objs/fly", 0);
+    assertXPath(pXmlDoc, "/root/page[4]/body/txt/anchored/fly", 0);
+    assertXPath(pXmlDoc, "/root/page", 4);
+}
+
 CPPUNIT_TEST_FIXTURE(SwLayoutWriter2, testRedlineCharAttributes)
 {
     createSwDoc("redline_charatr.fodt");
diff --git a/sw/source/core/layout/flylay.cxx b/sw/source/core/layout/flylay.cxx
index b1bfe32aab10..40b8547811fd 100644
--- a/sw/source/core/layout/flylay.cxx
+++ b/sw/source/core/layout/flylay.cxx
@@ -220,7 +220,7 @@ void SwFlyFreeFrame::MakeAll(vcl::RenderContext* 
/*pRenderContext*/)
             else
                 // #i26791# - use new method <MakeObjPos()>
                 MakeObjPos();
-            if( aOldPos == aRectFnSet.GetPos(getFrameArea()) )
+            if (!IsForceNotifyNewBackground() && aOldPos == 
aRectFnSet.GetPos(getFrameArea()))
             {
                 if( !isFrameAreaPositionValid() && GetAnchorFrame()->IsInSct() 
&&
                     
!GetAnchorFrame()->FindSctFrame()->isFrameAreaDefinitionValid() )
diff --git a/sw/source/core/layout/frmtool.cxx 
b/sw/source/core/layout/frmtool.cxx
index 193478da450e..bc0231e67307 100644
--- a/sw/source/core/layout/frmtool.cxx
+++ b/sw/source/core/layout/frmtool.cxx
@@ -691,6 +691,11 @@ void SwFlyNotify::ImplDestroy()
         }
         pFly->ResetNotifyBack();
     }
+    if (pFly->IsForceNotifyNewBackground())
+    {
+        pFly->NotifyBackground(pFly->FindPageFrame(), 
pFly->GetObjRectWithSpaces(), PrepareHint::FlyFrameArrive);
+        pFly->SetForceNotifyNewBackground(false);
+    }
 
     //Have the size or the position changed,
     //so should the view know this.
diff --git a/sw/source/core/layout/layact.cxx b/sw/source/core/layout/layact.cxx
index f0ac091d16ea..1996f8e319e6 100644
--- a/sw/source/core/layout/layact.cxx
+++ b/sw/source/core/layout/layact.cxx
@@ -1682,6 +1682,12 @@ bool SwLayAction::FormatContent(SwPageFrame *const pPage)
                 pObj->InvalidateObjPos();
                 ::Notify_Background(pObj->GetDrawObj(), pPage,
                     pObj->GetObjRect(), PrepareHint::FlyFrameLeave, false);
+                // tdf#148897 in case the fly moves back to this page before
+                // being positioned again, the SwFlyNotify / ::Notify() could
+                // conclude that it didn't move at all and not call
+                // NotifyBackground(); note: pObj->SetObjTop(FAR_AWAY) results
+                // in wrong positions, use different approach!
+                pObj->SetForceNotifyNewBackground(true);
             }
             if (!moved.empty())
             {

Reply via email to