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 <[email protected]> AuthorDate: Tue Jan 12 17:10:49 2021 +0100 Commit: Miklos Vajna <[email protected]> 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 <[email protected]> AuthorDate: Wed Jan 13 15:10:48 2021 +0100 Commit: Miklos Vajna <[email protected]> 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 <[email protected]> AuthorDate: Tue Nov 24 17:26:32 2020 +0100 Commit: Miklos Vajna <[email protected]> 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); } _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
