sw/qa/core/layout/data/floattable-hori-pos.docx |binary
 sw/qa/core/layout/flycnt.cxx                    |   34 ++++++++++++++++++++++++
 sw/qa/uitest/writer_tests6/tdf124675.py         |   27 +++++++++----------
 sw/source/core/text/frmform.cxx                 |   34 ++++++++++++++----------
 uitest/uitest/test.py                           |   13 +++++++++
 5 files changed, 81 insertions(+), 27 deletions(-)

New commits:
commit 3ef536a6755ffdcfc2657453444728cd0062d284
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Thu Mar 23 08:09:01 2023 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Mar 29 10:17:08 2023 +0000

    sw floattable: fix bad position of follow fly if anchor is positioned late
    
    The bugdoc has a split fly, the master is centered horizontally. That
    means the follow should be centered as well, but it was aligned to the
    left.
    
    The problem is that the follow fly was positioned when the anchor was
    not positioned at all (its top left was 0,0) and then there was no
    invalidation of the fly position to recalc it later when the anchor got
    positioned. The existing InvalidatePos() call is not enough because once
    a fly is formatted, its position gets locked and only
    unlockPositionOfObjects() at the end of the layout process will unlock
    it.
    
    Fix the problem similar to what lcl_InvalidateLowerObjs() for SwTabFrame
    does: if we know that the position of the anchor changed, then unlock
    the position before invalidating it.
    
    If this leads to unwanted re-positioning of flys, it would be perhaps
    possible to do this when the anchor position changes from 0,0 to a valid
    position, but for now just do this all time the anchor position changes.
    
    (cherry picked from commit 12a9009a1c19ee26c65fb44fc90f3432c88ab6a5)
    
    Change-Id: I811bdfa1eb6705ff3de6ec77111e9500617e8bee
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149477
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/core/layout/data/floattable-hori-pos.docx 
b/sw/qa/core/layout/data/floattable-hori-pos.docx
new file mode 100644
index 000000000000..7a5e033a4928
Binary files /dev/null and b/sw/qa/core/layout/data/floattable-hori-pos.docx 
differ
diff --git a/sw/qa/core/layout/flycnt.cxx b/sw/qa/core/layout/flycnt.cxx
index 528b3bc4cbc8..b9ab0ac116cb 100644
--- a/sw/qa/core/layout/flycnt.cxx
+++ b/sw/qa/core/layout/flycnt.cxx
@@ -509,6 +509,40 @@ CPPUNIT_TEST_FIXTURE(Test, testSplitFlyCompat14Body)
     SwFrame* pRow2 = pTab2->GetLower();
     CPPUNIT_ASSERT(!pRow2->GetNext());
 }
+
+CPPUNIT_TEST_FIXTURE(Test, testSplitFlyFollowHorizontalPosition)
+{
+    // Given a document with 2 pages, master fly on page 1, follow fly on page 
2:
+    SwModelTestBase::FlySplitGuard aGuard;
+    createSwDoc("floattable-hori-pos.docx");
+
+    // When laying out that document:
+    calcLayout();
+
+    // Then make sure that the follow fly doesn't have a different horizontal 
position:
+    SwDoc* pDoc = getSwDoc();
+    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+    auto pPage1 = dynamic_cast<SwPageFrame*>(pLayout->Lower());
+    CPPUNIT_ASSERT(pPage1);
+    const SwSortedObjs& rPage1Objs = *pPage1->GetSortedObjs();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage1Objs.size());
+    auto pPage1Fly = dynamic_cast<SwFlyAtContentFrame*>(rPage1Objs[0]);
+    CPPUNIT_ASSERT(pPage1Fly);
+    tools::Long nPage1FlyLeft = pPage1Fly->getFrameArea().Left();
+    auto pPage2 = dynamic_cast<SwPageFrame*>(pPage1->GetNext());
+    CPPUNIT_ASSERT(pPage2);
+    const SwSortedObjs& rPage2Objs = *pPage2->GetSortedObjs();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPage2Objs.size());
+    auto pPage2Fly = dynamic_cast<SwFlyAtContentFrame*>(rPage2Objs[0]);
+    CPPUNIT_ASSERT(pPage2Fly);
+    tools::Long nPage2FlyLeft = pPage2Fly->getFrameArea().Left();
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: 5528
+    // - Actual  : 284
+    // i.e. the follow fly was pushed towards the left, instead of having the 
same position as the
+    // master fly.
+    CPPUNIT_ASSERT_EQUAL(nPage1FlyLeft, nPage2FlyLeft);
+}
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/frmform.cxx b/sw/source/core/text/frmform.cxx
index 83980f9c8b11..f756b186c464 100644
--- a/sw/source/core/text/frmform.cxx
+++ b/sw/source/core/text/frmform.cxx
@@ -340,25 +340,31 @@ bool SwTextFrame::CalcFollow(TextFrameIndex const 
nTextOfst)
 
 void SwTextFrame::MakePos()
 {
+    Point aOldPos = getFrameArea().Pos();
     SwFrame::MakePos();
 
-    // Find the master frame.
-    const SwTextFrame* pMaster = this;
-    while (pMaster->IsFollow())
+    // Recalc split flys if our position changed.
+    if (aOldPos != getFrameArea().Pos())
     {
-        pMaster = pMaster->FindMaster();
-    }
-    // Find which flys are effectively anchored to this frame.
-    for (const auto& pFly : pMaster->GetSplitFlyDrawObjs())
-    {
-        SwTextFrame* pFlyAnchor = pFly->FindAnchorCharFrame();
-        if (pFlyAnchor != this)
+        // Find the master frame.
+        const SwTextFrame* pMaster = this;
+        while (pMaster->IsFollow())
+        {
+            pMaster = pMaster->FindMaster();
+        }
+        // Find which flys are effectively anchored to this frame.
+        for (const auto& pFly : pMaster->GetSplitFlyDrawObjs())
         {
-            continue;
+            SwTextFrame* pFlyAnchor = pFly->FindAnchorCharFrame();
+            if (pFlyAnchor != this)
+            {
+                continue;
+            }
+            // Possibly this fly was positioned relative to us, invalidate its 
position now that our
+            // position is changed.
+            pFly->UnlockPosition();
+            pFly->InvalidatePos();
         }
-        // Possibly this fly was positioned relative to us, invalidate its 
position now that our
-        // position is changed.
-        pFly->InvalidatePos();
     }
 
     // Inform LOK clients about change in position of redlines (if any)
commit 3ff9de9e06017375ea9abfc20b3eb0c7cd91c254
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Wed Mar 22 11:34:54 2023 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Mar 29 10:17:00 2023 +0000

    sw floattable: fix current page number when editing document with a split 
fly
    
    UITest_writer_tests6's
    tdf124675.tdf124675.test_tdf124675_crash_moving_SwTextFrame_previous_page
    failed in the SW_FORCE_FLY_SPLIT=1 case, since the current page after
    typing was 3, not 2.
    
    It seems this change is wanted, since the total page count increases by
    2, so it's consistent that the current page increases similarly with
    typing. Also, repeating the UITest in Word (after positioning the cursor
    at the top paragraph in the document) also produces page 3 as the
    current page.
    
    Fix the problem by locally enabling split flys for this test and then we
    can assert that we match Word. This requires a new context manager, but
    that set_config() is really similar to other context managers in the
    class that return no value.
    
    The original purpose of the test was to make sure we don't crash,
    anyway.
    
    (cherry picked from commit 015da04a8f3e1368c6b9668ca22d7e320e1ecae6)
    
    Change-Id: Id0dfde23a8726c8799950a6e4fdd1d85f135eafc
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149376
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>

diff --git a/sw/qa/uitest/writer_tests6/tdf124675.py 
b/sw/qa/uitest/writer_tests6/tdf124675.py
index 40eb2987e260..93bae8ea9284 100644
--- a/sw/qa/uitest/writer_tests6/tdf124675.py
+++ b/sw/qa/uitest/writer_tests6/tdf124675.py
@@ -14,23 +14,24 @@ from uitest.uihelper.common import get_state_as_dict, 
get_url_for_data_file
 
 class tdf124675(UITestCase):
    def test_tdf124675_crash_moving_SwTextFrame_previous_page(self):
-        with self.ui_test.load_file(get_url_for_data_file("tdf124675.docx")) 
as writer_doc:
-            xWriterDoc = self.xUITest.getTopFocusWindow()
-            xWriterEdit = xWriterDoc.getChild("writer_edit")
+        with 
self.ui_test.set_config('/org.openoffice.Office.Writer/Filter/Import/DOCX/ImportFloatingTableAsSplitFly',
 True):
+            with 
self.ui_test.load_file(get_url_for_data_file("tdf124675.docx")) as writer_doc:
+                xWriterDoc = self.xUITest.getTopFocusWindow()
+                xWriterEdit = xWriterDoc.getChild("writer_edit")
 
-            self.assertEqual(writer_doc.CurrentController.PageCount, 2)
-            self.assertEqual(get_state_as_dict(xWriterEdit)["CurrentPage"], 
"1")
+                self.assertEqual(writer_doc.CurrentController.PageCount, 2)
+                
self.assertEqual(get_state_as_dict(xWriterEdit)["CurrentPage"], "1")
 
-            for i in range(52):
-                xWriterEdit.executeAction("TYPE", mkPropertyValues({"KEYCODE": 
"RETURN"}))
+                for i in range(52):
+                    xWriterEdit.executeAction("TYPE", 
mkPropertyValues({"KEYCODE": "RETURN"}))
 
-            self.assertEqual(writer_doc.CurrentController.PageCount, 4)
-            self.assertEqual(get_state_as_dict(xWriterEdit)["CurrentPage"], 
"2")
+                self.assertEqual(writer_doc.CurrentController.PageCount, 4)
+                
self.assertEqual(get_state_as_dict(xWriterEdit)["CurrentPage"], "3")
 
-            for i in range(52):
-                self.xUITest.executeCommand(".uno:Undo")
+                for i in range(52):
+                    self.xUITest.executeCommand(".uno:Undo")
 
-            self.assertEqual(writer_doc.CurrentController.PageCount, 2)
-            self.assertEqual(get_state_as_dict(xWriterEdit)["CurrentPage"], 
"1")
+                self.assertEqual(writer_doc.CurrentController.PageCount, 2)
+                
self.assertEqual(get_state_as_dict(xWriterEdit)["CurrentPage"], "1")
 
 # vim: set shiftwidth=4 softtabstop=4 expandtab:
diff --git a/uitest/uitest/test.py b/uitest/uitest/test.py
index 5ed20add799c..5442d46b1d90 100644
--- a/uitest/uitest/test.py
+++ b/uitest/uitest/test.py
@@ -104,6 +104,19 @@ class UITest(object):
         finally:
             self.close_doc()
 
+    # Resets the setting to the old value at exit
+    @contextmanager
+    def set_config(self, path, new_value):
+        xChanges = 
self._xContext.ServiceManager.createInstanceWithArgumentsAndContext('com.sun.star.configuration.ReadWriteAccess',
 ("",), self._xContext)
+        try:
+            old_value = xChanges.getByHierarchicalName(path)
+            xChanges.replaceByHierarchicalName(path, new_value)
+            xChanges.commitChanges()
+            yield
+        finally:
+            xChanges.replaceByHierarchicalName(path, old_value)
+            xChanges.commitChanges()
+
     # Calls UITest.close_doc at exit
     @contextmanager
     def load_empty_file(self, app):

Reply via email to