[Libreoffice-commits] core.git: Branch 'distro/collabora/co-2021' - 3 commits - oox/source sfx2/source sw/qa sw/source

Miklos Vajna (via logerrit) logerrit at kemper.freedesktop.org
Mon Mar 29 09:30:34 UTC 2021


 oox/source/drawingml/diagram/diagramlayoutatoms.cxx         |   70 ++++++-----
 oox/source/drawingml/diagram/diagramlayoutatoms.hxx         |   10 +
 sfx2/source/view/viewsh.cxx                                 |   14 +-
 sw/qa/extras/tiledrendering/data/table-paint-invalidate.odt |binary
 sw/qa/extras/tiledrendering/tiledrendering.cxx              |   76 ++++++++++++
 sw/source/uibase/docvw/edtwin.cxx                           |   10 +
 sw/source/uibase/docvw/edtwin2.cxx                          |   11 +
 7 files changed, 156 insertions(+), 35 deletions(-)

New commits:
commit b22578acf41e8f24248014560e288e17a3849c4c
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Tue Jan 12 17:10:49 2021 +0100
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Mon Mar 29 10:45:42 2021 +0200

    sw edit win: fix read-only selections while handling ExtTextInput
    
    When typing into a protected section (or other read-only area), the code
    goes through SwEditWin::KeyInput(), which checks for HasReadonlySel(),
    and calls into sw::DocumentContentOperationsManager::InsertString() in
    the read-write case.
    
    When typing via ExtTextInput (e.g. Online), then SwEditWin::Command()
    called into sw::DocumentContentOperationsManager::InsertString() without
    such a check.
    
    The convention is to do a read-only check in the first Writer function
    called by vcl, so handle this in SwEditWin::Command(), to have exactly 1
    read-only popup on typing a character.
    
    (cherry picked from commit 0c03a97fb8844ad0de1abea79b5265617a509460)
    
    Conflicts:
            sw/qa/extras/tiledrendering/tiledrendering.cxx
    
    Change-Id: I7d002e7d76bffeb6f16750de735c5bbf13a7bba9

diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx
index afb261b4d4bc..f8ee487ef788 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -17,6 +17,7 @@
 #include <com/sun/star/frame/XDispatchResultListener.hpp>
 #include <com/sun/star/frame/XStorable.hpp>
 #include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/text/XTextViewCursorSupplier.hpp>
 
 #include <test/helper/transferable.hxx>
 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
@@ -145,6 +146,7 @@ public:
     void testDropDownFormFieldButtonNoSelection();
     void testDropDownFormFieldButtonNoItem();
     void testTablePaintInvalidate();
+    void testExtTextInputReadOnly();
 
     CPPUNIT_TEST_SUITE(SwTiledRenderingTest);
     CPPUNIT_TEST(testRegisterCallback);
@@ -217,6 +219,7 @@ public:
     CPPUNIT_TEST(testDropDownFormFieldButtonNoSelection);
     CPPUNIT_TEST(testDropDownFormFieldButtonNoItem);
     CPPUNIT_TEST(testTablePaintInvalidate);
+    CPPUNIT_TEST(testExtTextInputReadOnly);
     CPPUNIT_TEST_SUITE_END();
 
 private:
@@ -2869,6 +2872,46 @@ void SwTiledRenderingTest::testTablePaintInvalidate()
     CPPUNIT_ASSERT_EQUAL(0, m_nInvalidations);
 }
 
+void SwTiledRenderingTest::testExtTextInputReadOnly()
+{
+    // Create a document with a protected section + a normal paragraph after it.
+    SwXTextDocument* pXTextDocument = createDoc();
+    uno::Reference<text::XTextViewCursorSupplier> xController(
+        pXTextDocument->getCurrentController(), uno::UNO_QUERY);
+    uno::Reference<text::XTextViewCursor> xCursor = xController->getViewCursor();
+    uno::Reference<text::XText> xText = xCursor->getText();
+    uno::Reference<text::XTextContent> xSection(
+        pXTextDocument->createInstance("com.sun.star.text.TextSection"), uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> xSectionProps(xSection, uno::UNO_QUERY);
+    xSectionProps->setPropertyValue("IsProtected", uno::Any(true));
+    xText->insertTextContent(xCursor, xSection, /*bAbsorb=*/true);
+
+    // First paragraph is the protected section, is it empty?
+    VclPtr<vcl::Window> pEditWin = pXTextDocument->getDocWindow();
+    CPPUNIT_ASSERT(pEditWin);
+    CPPUNIT_ASSERT(getParagraph(1)->getString().isEmpty());
+
+    // Try to type into the protected section, is it still empty?
+    SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell();
+    pWrtShell->SttEndDoc(/*bStt=*/true);
+    SfxLokHelper::postExtTextEventAsync(pEditWin, LOK_EXT_TEXTINPUT, "x");
+    SfxLokHelper::postExtTextEventAsync(pEditWin, LOK_EXT_TEXTINPUT_END, "x");
+    Scheduler::ProcessEventsToIdle();
+    // Without the accompanying fix in place, this test would have failed, as it was possible to
+    // type into the protected section.
+    CPPUNIT_ASSERT(getParagraph(1)->getString().isEmpty());
+
+    // Second paragraph is a normal paragraph, is it empty?
+    pWrtShell->Down(/*bSelect=*/false);
+    CPPUNIT_ASSERT(getParagraph(2)->getString().isEmpty());
+
+    // Try to type into the protected section, does it have the typed content?
+    SfxLokHelper::postExtTextEventAsync(pEditWin, LOK_EXT_TEXTINPUT, "x");
+    SfxLokHelper::postExtTextEventAsync(pEditWin, LOK_EXT_TEXTINPUT_END, "x");
+    Scheduler::ProcessEventsToIdle();
+    CPPUNIT_ASSERT_EQUAL(OUString("x"), getParagraph(2)->getString());
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SwTiledRenderingTest);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx
index 9ad8275b7b1b..535a9e1aaf79 100644
--- a/sw/source/uibase/docvw/edtwin.cxx
+++ b/sw/source/uibase/docvw/edtwin.cxx
@@ -5544,7 +5544,7 @@ void SwEditWin::Command( const CommandEvent& rCEvt )
     {
         bool bIsDocReadOnly = m_rView.GetDocShell()->IsReadOnly() &&
                               rSh.IsCursorReadonly();
-        if(!bIsDocReadOnly)
+        if (!bIsDocReadOnly && !rSh.HasReadonlySel())
         {
             if( m_pQuickHlpData->m_bIsDisplayed )
                 m_pQuickHlpData->Stop( rSh );
@@ -5576,6 +5576,14 @@ void SwEditWin::Command( const CommandEvent& rCEvt )
                 }
             }
         }
+
+        if (rSh.HasReadonlySel())
+        {
+            // Inform the user that the request has been ignored.
+            auto xInfo = std::make_shared<weld::GenericDialogController>(
+                GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog");
+            weld::DialogController::runAsync(xInfo, [](sal_Int32 /*nResult*/) {});
+        }
     }
     break;
     case CommandEventId::CursorPos:
commit 009c6c8e10d6fe946ef4f9b8212f9c02c843fe85
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Wed Jan 13 15:10:48 2021 +0100
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Mon Mar 29 10:43:07 2021 +0200

    oox smartart: extract pyra algo from AlgAtom::layoutShape()
    
    AlgAtom::layoutShape() is more or less the single function where all
    layouting happens for all algoritms. Extract the pyra algorithm part
    from it to a separate PyraAlg::layoutShapeChildren() before that
    function grows too large.
    
    (cherry picked from commit 318438a680e6bf5c2c592d5e997f6f45a4ae8e5f)
    
    Change-Id: I097ac9ed6110536bbeb8a26ab35a8ee8a79d5b33

diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
index 122c8d3828db..2f086421f818 100644
--- a/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
+++ b/oox/source/drawingml/diagram/diagramlayoutatoms.cxx
@@ -440,6 +440,43 @@ void SnakeAlg::layoutShapeChildren(const AlgAtom::ParamMap& rMap, const ShapePtr
     }
 }
 
+void PyraAlg::layoutShapeChildren(const ShapePtr& rShape)
+{
+    if (rShape->getChildren().empty() || rShape->getSize().Width == 0
+        || rShape->getSize().Height == 0)
+        return;
+
+    // const sal_Int32 nDir = maMap.count(XML_linDir) ? maMap.find(XML_linDir)->second : XML_fromT;
+    // const sal_Int32 npyraAcctPos = maMap.count(XML_pyraAcctPos) ? maMap.find(XML_pyraAcctPos)->second : XML_bef;
+    // const sal_Int32 ntxDir = maMap.count(XML_txDir) ? maMap.find(XML_txDir)->second : XML_fromT;
+    // const sal_Int32 npyraLvlNode = maMap.count(XML_pyraLvlNode) ? maMap.find(XML_pyraLvlNode)->second : XML_level;
+    // uncomment when use in code.
+
+    sal_Int32 nCount = rShape->getChildren().size();
+    double fAspectRatio = 0.32;
+
+    awt::Size aChildSize = rShape->getSize();
+    aChildSize.Width /= nCount;
+    aChildSize.Height /= nCount;
+
+    awt::Point aCurrPos(0, 0);
+    aCurrPos.X = fAspectRatio * aChildSize.Width * (nCount - 1);
+    aCurrPos.Y = fAspectRatio * aChildSize.Height;
+
+    for (auto& aCurrShape : rShape->getChildren())
+    {
+        aCurrShape->setPosition(aCurrPos);
+        if (nCount > 1)
+        {
+            aCurrPos.X -= aChildSize.Height / (nCount - 1);
+        }
+        aChildSize.Width += aChildSize.Height;
+        aCurrShape->setSize(aChildSize);
+        aCurrShape->setChildSize(aChildSize);
+        aCurrPos.Y += (aChildSize.Height);
+    }
+}
+
 IteratorAttr::IteratorAttr( )
     : mnCnt( -1 )
     , mbHideLastTrans( true )
@@ -1636,38 +1673,7 @@ void AlgAtom::layoutShape(const ShapePtr& rShape, const std::vector<Constraint>&
 
         case XML_pyra:
         {
-            if (rShape->getChildren().empty() || rShape->getSize().Width == 0 || rShape->getSize().Height == 0)
-                break;
-
-            // const sal_Int32 nDir = maMap.count(XML_linDir) ? maMap.find(XML_linDir)->second : XML_fromT;
-            // const sal_Int32 npyraAcctPos = maMap.count(XML_pyraAcctPos) ? maMap.find(XML_pyraAcctPos)->second : XML_bef;
-            // const sal_Int32 ntxDir = maMap.count(XML_txDir) ? maMap.find(XML_txDir)->second : XML_fromT;
-            // const sal_Int32 npyraLvlNode = maMap.count(XML_pyraLvlNode) ? maMap.find(XML_pyraLvlNode)->second : XML_level;
-            // uncomment when use in code.
-
-            sal_Int32 nCount = rShape->getChildren().size();
-            double fAspectRatio = 0.32;
-
-            awt::Size aChildSize = rShape->getSize();
-            aChildSize.Width /= nCount;
-            aChildSize.Height /= nCount;
-
-            awt::Point aCurrPos(0, 0);
-            aCurrPos.X = fAspectRatio*aChildSize.Width*(nCount-1);
-            aCurrPos.Y = fAspectRatio*aChildSize.Height;
-
-            for (auto & aCurrShape : rShape->getChildren())
-            {
-                aCurrShape->setPosition(aCurrPos);
-                if (nCount > 1)
-                {
-                    aCurrPos.X -= aChildSize.Height / (nCount - 1);
-                }
-                aChildSize.Width += aChildSize.Height;
-                aCurrShape->setSize(aChildSize);
-                aCurrShape->setChildSize(aChildSize);
-                aCurrPos.Y += (aChildSize.Height);
-            }
+            PyraAlg::layoutShapeChildren(rShape);
             break;
         }
 
diff --git a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
index bc59e3ab307a..149be2c97338 100644
--- a/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
+++ b/oox/source/drawingml/diagram/diagramlayoutatoms.hxx
@@ -209,6 +209,16 @@ public:
                                     const std::vector<Constraint>& rConstraints);
 };
 
+/**
+ * Lays out child layout nodes along a vertical path and works with the trapezoid shape to create a
+ * pyramid.
+ */
+class PyraAlg
+{
+public:
+    static void layoutShapeChildren(const ShapePtr& rShape);
+};
+
 class ForEachAtom
     : public LayoutAtom
 {
commit 46bf8a82966ab0940d1f6d5393074d5b4243aa3f
Author:     Miklos Vajna <vmiklos at collabora.com>
AuthorDate: Tue Nov 24 17:26:32 2020 +0100
Commit:     Miklos Vajna <vmiklos at collabora.com>
CommitDate: Mon Mar 29 10:33:21 2021 +0200

    sw tiled rendering: fix paint->invalidation loop when paint is started by vcl
    
    SwViewShell::PaintTile() already calls
    comphelper::LibreOfficeKit::setTiledPainting(), so by the time it would
    rearch SwViewShell::Paint(), callbacks (e.g. invalidations) are ignored
    during paint.
    
    Do the same for SwEditWin::Paint(), where we processed invalidations
    during paint, potentially leading to paint->invalidation loops.
    
    (cherry picked from commit 0f65b4b6f33891a724bee5356aa5549c76fa0ce3)
    
    Change-Id: I8280f5c2571beeae6c0f2986d275dde3c2d33161

diff --git a/sfx2/source/view/viewsh.cxx b/sfx2/source/view/viewsh.cxx
index d35253d1342a..2da4bc1e81bd 100644
--- a/sfx2/source/view/viewsh.cxx
+++ b/sfx2/source/view/viewsh.cxx
@@ -1463,8 +1463,18 @@ void SfxViewShell::libreOfficeKitViewCallback(int nType, const char* pPayload) c
     if (!comphelper::LibreOfficeKit::isActive())
         return;
 
-    if (comphelper::LibreOfficeKit::isTiledPainting() && nType != LOK_CALLBACK_FORM_FIELD_BUTTON)
-        return;
+    if (comphelper::LibreOfficeKit::isTiledPainting())
+    {
+        switch (nType)
+        {
+        case LOK_CALLBACK_FORM_FIELD_BUTTON:
+        case LOK_CALLBACK_TEXT_SELECTION:
+            break;
+        default:
+            // Reject e.g. invalidate during paint.
+            return;
+        }
+    }
 
     if (pImpl->m_bTiledSearching)
     {
diff --git a/sw/qa/extras/tiledrendering/data/table-paint-invalidate.odt b/sw/qa/extras/tiledrendering/data/table-paint-invalidate.odt
new file mode 100644
index 000000000000..b42c5cc51588
Binary files /dev/null and b/sw/qa/extras/tiledrendering/data/table-paint-invalidate.odt differ
diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx
index dc57ef1e451a..afb261b4d4bc 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -144,6 +144,7 @@ public:
     void testDropDownFormFieldButtonEditing();
     void testDropDownFormFieldButtonNoSelection();
     void testDropDownFormFieldButtonNoItem();
+    void testTablePaintInvalidate();
 
     CPPUNIT_TEST_SUITE(SwTiledRenderingTest);
     CPPUNIT_TEST(testRegisterCallback);
@@ -215,6 +216,7 @@ public:
     CPPUNIT_TEST(testDropDownFormFieldButtonEditing);
     CPPUNIT_TEST(testDropDownFormFieldButtonNoSelection);
     CPPUNIT_TEST(testDropDownFormFieldButtonNoItem);
+    CPPUNIT_TEST(testTablePaintInvalidate);
     CPPUNIT_TEST_SUITE_END();
 
 private:
@@ -2836,6 +2838,37 @@ void SwTiledRenderingTest::testDropDownFormFieldButtonNoItem()
     }
 }
 
+void SwTiledRenderingTest::testTablePaintInvalidate()
+{
+    // Load a document with a table in it.
+    SwXTextDocument* pXTextDocument = createDoc("table-paint-invalidate.odt");
+    SwWrtShell* pWrtShell = pXTextDocument->GetDocShell()->GetWrtShell();
+    pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&SwTiledRenderingTest::callback, this);
+    // Enter the table.
+    pWrtShell->Down(/*bSelect=*/false);
+    Scheduler::ProcessEventsToIdle();
+    m_nInvalidations = 0;
+
+    // Paint a tile.
+    size_t nCanvasWidth = 256;
+    size_t nCanvasHeight = 256;
+    std::vector<unsigned char> aPixmap(nCanvasWidth * nCanvasHeight * 4, 0);
+    ScopedVclPtrInstance<VirtualDevice> pDevice(DeviceFormat::DEFAULT);
+    pDevice->SetBackground(Wallpaper(COL_TRANSPARENT));
+    pDevice->SetOutputSizePixelScaleOffsetAndBuffer(Size(nCanvasWidth, nCanvasHeight),
+                                                    Fraction(1.0), Point(), aPixmap.data());
+    pXTextDocument->paintTile(*pDevice, nCanvasWidth, nCanvasHeight, m_aInvalidation.getX(),
+                              m_aInvalidation.getY(), /*nTileWidth=*/1000,
+                              /*nTileHeight=*/1000);
+    Scheduler::ProcessEventsToIdle();
+
+    // Without the accompanying fix in place, this test would have failed with
+    // - Expected: 0
+    // - Actual  : 5
+    // i.e. paint generated an invalidation, which caused a loop.
+    CPPUNIT_ASSERT_EQUAL(0, m_nInvalidations);
+}
+
 CPPUNIT_TEST_SUITE_REGISTRATION(SwTiledRenderingTest);
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/source/uibase/docvw/edtwin2.cxx b/sw/source/uibase/docvw/edtwin2.cxx
index 18003f48bb99..ca1aec7faf7f 100644
--- a/sw/source/uibase/docvw/edtwin2.cxx
+++ b/sw/source/uibase/docvw/edtwin2.cxx
@@ -50,6 +50,7 @@
 #include <txtfrm.hxx>
 #include <ndtxt.hxx>
 #include <FrameControlsManager.hxx>
+#include <comphelper/lok.hxx>
 
 static OUString lcl_GetRedlineHelp( const SwRangeRedline& rRedl, bool bBalloon )
 {
@@ -431,7 +432,17 @@ void SwEditWin::Paint(vcl::RenderContext& rRenderContext, const tools::Rectangle
     else
     {
         pWrtShell->setOutputToWindow(true);
+        bool bTiledPainting = false;
+        if (comphelper::LibreOfficeKit::isActive())
+        {
+            bTiledPainting = comphelper::LibreOfficeKit::isTiledPainting();
+            comphelper::LibreOfficeKit::setTiledPainting(true);
+        }
         pWrtShell->Paint(rRenderContext, rRect);
+        if (comphelper::LibreOfficeKit::isActive())
+        {
+            comphelper::LibreOfficeKit::setTiledPainting(bTiledPainting);
+        }
         pWrtShell->setOutputToWindow(false);
     }
 


More information about the Libreoffice-commits mailing list