diff options
-rw-r--r-- | editeng/source/editeng/editview.cxx | 5 | ||||
-rw-r--r-- | include/vcl/window.hxx | 2 | ||||
-rw-r--r-- | sc/qa/unit/tiledrendering/tiledrendering.cxx | 115 | ||||
-rw-r--r-- | sc/source/ui/inc/gridwin.hxx | 1 | ||||
-rw-r--r-- | sc/source/ui/view/gridwin4.cxx | 26 | ||||
-rw-r--r-- | vcl/source/window/paint.cxx | 5 |
6 files changed, 153 insertions, 1 deletions
diff --git a/editeng/source/editeng/editview.cxx b/editeng/source/editeng/editview.cxx index e047e6a41ffa..ff979af96698 100644 --- a/editeng/source/editeng/editview.cxx +++ b/editeng/source/editeng/editview.cxx @@ -231,7 +231,10 @@ void EditView::InvalidateOtherViewWindows( const tools::Rectangle& rInvRect ) for (auto& pWin : pImpEditView->aOutWindowSet) { if (pWin) - pWin->Invalidate( bNegativeX ? lcl_negateRectX(rInvRect) : rInvRect ); + { + if (!pWin->InvalidateByForeignEditView(this)) + pWin->Invalidate( bNegativeX ? lcl_negateRectX(rInvRect) : rInvRect ); + } } } } diff --git a/include/vcl/window.hxx b/include/vcl/window.hxx index 640e9c6c9983..74f1d395e9ad 100644 --- a/include/vcl/window.hxx +++ b/include/vcl/window.hxx @@ -62,6 +62,7 @@ class VclWindowEvent; class AllSettings; class InputContext; class VclEventListeners; +class EditView; enum class ImplPaintFlags; enum class VclEventId; enum class PointerStyle; @@ -967,6 +968,7 @@ public: */ virtual void LogicInvalidate(const tools::Rectangle* pRectangle); + virtual bool InvalidateByForeignEditView(EditView* ); /** * Notification about some rectangle of the output device got invalidated. Used for the * dialogs and floating windows (e.g. context menu, popup). diff --git a/sc/qa/unit/tiledrendering/tiledrendering.cxx b/sc/qa/unit/tiledrendering/tiledrendering.cxx index 737c1a534cce..ee2b50522e3f 100644 --- a/sc/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx @@ -9,6 +9,7 @@ #include <test/unoapixml_test.hxx> #include <test/helper/transferable.hxx> +#include <cppunit/tools/StringHelper.h> #include <boost/property_tree/json_parser.hpp> #include <LibreOfficeKit/LibreOfficeKitEnums.h> @@ -64,6 +65,32 @@ static std::ostream& operator<<(std::ostream& os, ViewShellId const & id) os << static_cast<sal_Int32>(id); return os; } +namespace { +// for passing data to testInvalidateOnTextEditWithDifferentZoomLevels +struct ColRowZoom +{ + SCCOL col; + SCROW row; + int zoom; +}; +} + +CPPUNIT_NS_BEGIN +namespace StringHelper +{ +// used by CPPUNIT_TEST_PARAMETERIZED for testInvalidateOnTextEditWithDifferentZoomLevels +template<> +inline std::string toString(const ColRowZoom& item) +{ + std::ostringstream ss; + ss << "zoom level: " << item.zoom << ", " + "col: " << item.col << ", " + "row: " << item.row; + return ss.str(); +} +} +CPPUNIT_NS_END + class ScTiledRenderingTest : public UnoApiXmlTest { public: @@ -3144,6 +3171,94 @@ CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testGetViewRenderState) CPPUNIT_ASSERT_EQUAL(";Default"_ostr, pModelObj->getViewRenderState()); } +/* + * testInvalidateOnTextEditWithDifferentZoomLevels + * steps: + * set view 1 zoom to the passed zoom level + * in view 1 type a char at the passed cell address + * store invalidation rectangle + * exit from in place editing (press esc) + * create view 2 (keep 100% zoom) + * go to the same cell address used in view 1 + * type a char into the cell + * get invalidation rectangle for view 1 + * check if the invalidation rectangle is equal to the one stored previously +*/ +class testInvalidateOnTextEditWithDifferentZoomLevels : public ScTiledRenderingTest +{ +public: + void TestBody(const ColRowZoom& rData); + CPPUNIT_TEST_SUITE(testInvalidateOnTextEditWithDifferentZoomLevels); + CPPUNIT_TEST_PARAMETERIZED(TestBody, + std::initializer_list<ColRowZoom> + { + // zoom level 120% + {0, 999, 1}, {99, 0, 1}, + // zoom level 40% + {0, 999, -5}, {99, 0, -5} + }); + CPPUNIT_TEST_SUITE_END(); +}; +CPPUNIT_TEST_SUITE_REGISTRATION(testInvalidateOnTextEditWithDifferentZoomLevels); + +void testInvalidateOnTextEditWithDifferentZoomLevels::TestBody(const ColRowZoom& rData) +{ + ScModelObj* pModelObj = createDoc("empty.ods"); + CPPUNIT_ASSERT(pModelObj); + ScDocument* pDoc = pModelObj->GetDocument(); + CPPUNIT_ASSERT(pDoc); + OUString sZoomUnoCmd = ".uno:ZoomPlus"; + int nZoomLevel = rData.zoom; + if (nZoomLevel < 0) + { + nZoomLevel = -nZoomLevel; + sZoomUnoCmd = ".uno:ZoomMinus"; + } + // view #1 + ViewCallback aView1; + // set zoom level + for (int i = 0; i < nZoomLevel; ++i) + dispatchCommand(mxComponent, sZoomUnoCmd, {}); + Scheduler::ProcessEventsToIdle(); + auto* pTabViewShell1 = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current()); + CPPUNIT_ASSERT(pTabViewShell1); + // enable in place editing in view 1 + auto& rInvalidations = aView1.m_aInvalidations; + pTabViewShell1->SetCursor(rData.col, rData.row); + Scheduler::ProcessEventsToIdle(); + aView1.m_bInvalidateTiles = false; + rInvalidations.clear(); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT(aView1.m_bInvalidateTiles); + CPPUNIT_ASSERT(!rInvalidations.empty()); + tools::Rectangle aInvRect1 = rInvalidations[0]; + // end editing + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::ESCAPE); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE); + Scheduler::ProcessEventsToIdle(); + // view #2 + SfxLokHelper::createView(); + pModelObj->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + ViewCallback aView2; + Scheduler::ProcessEventsToIdle(); + auto* pTabViewShell2 = dynamic_cast<ScTabViewShell*>(SfxViewShell::Current()); + CPPUNIT_ASSERT(pTabViewShell2); + pTabViewShell2->SetCursor(rData.col, rData.row); + Scheduler::ProcessEventsToIdle(); + // text edit in view #2 + aView1.m_bInvalidateTiles = false; + rInvalidations.clear(); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); + pModelObj->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT(aView1.m_bInvalidateTiles); + CPPUNIT_ASSERT(!rInvalidations.empty()); + tools::Rectangle aInvRect2 = rInvalidations[0]; + CPPUNIT_ASSERT_EQUAL_MESSAGE("Invalidation rectangle is wrong.", aInvRect1, aInvRect2); +} + CPPUNIT_TEST_FIXTURE(ScTiledRenderingTest, testOpenURL) { // Given a document that has 2 views: diff --git a/sc/source/ui/inc/gridwin.hxx b/sc/source/ui/inc/gridwin.hxx index 37c38fe069a0..b86331d6f96e 100644 --- a/sc/source/ui/inc/gridwin.hxx +++ b/sc/source/ui/inc/gridwin.hxx @@ -381,6 +381,7 @@ public: void LogicInvalidate(const tools::Rectangle* pRectangle) override; void LogicInvalidatePart(const tools::Rectangle* pRectangle, int nPart); + bool InvalidateByForeignEditView(EditView* pEditView) override; /// Update the cell selection according to what handles have been dragged. /// @see vcl::ITiledRenderable::setTextSelection() for the values of nType. /// Coordinates are in pixels. diff --git a/sc/source/ui/view/gridwin4.cxx b/sc/source/ui/view/gridwin4.cxx index ea59babd3a14..b6ef7367ff68 100644 --- a/sc/source/ui/view/gridwin4.cxx +++ b/sc/source/ui/view/gridwin4.cxx @@ -671,6 +671,11 @@ int lcl_GetMultiLineHeight(EditEngine* pEditEngine) return nHeight; } + +tools::Rectangle lcl_negateRectX(const tools::Rectangle& rRect) +{ + return tools::Rectangle(-rRect.Right(), rRect.Top(), -rRect.Left(), rRect.Bottom()); +} } void ScGridWindow::DrawContent(OutputDevice &rDevice, const ScTableInfo& rTableInfo, ScOutputData& aOutputData, @@ -1767,6 +1772,27 @@ void ScGridWindow::LogicInvalidate(const tools::Rectangle* pRectangle) LogicInvalidatePart(pRectangle, pViewShell->getPart()); } +bool ScGridWindow::InvalidateByForeignEditView(EditView* pEditView) +{ + if (!pEditView) + return false; + + auto* pGridWin = dynamic_cast<ScGridWindow*>(pEditView->GetWindow()); + if (!pGridWin) + return false; + + const ScViewData& rViewData = pGridWin->getViewData(); + tools::Long nRefTabNo = rViewData.GetRefTabNo(); + tools::Long nX = rViewData.GetCurXForTab(nRefTabNo); + tools::Long nY = rViewData.GetCurYForTab(nRefTabNo); + + tools::Rectangle aPixRect = getViewData().GetEditArea(eWhich, nX, nY, this, nullptr, true); + tools::Rectangle aLogicRect = PixelToLogic(aPixRect, getViewData().GetLogicMode()); + Invalidate(pEditView->IsNegativeX() ? lcl_negateRectX(aLogicRect) : aLogicRect); + + return true; +} + void ScGridWindow::SetCellSelectionPixel(int nType, int nPixelX, int nPixelY) { ScTabView* pTabView = mrViewData.GetView(); diff --git a/vcl/source/window/paint.cxx b/vcl/source/window/paint.cxx index a98703ca255b..7cb1c969a983 100644 --- a/vcl/source/window/paint.cxx +++ b/vcl/source/window/paint.cxx @@ -1198,6 +1198,11 @@ void Window::LogicInvalidate(const tools::Rectangle* pRectangle) PixelInvalidate(nullptr); } +bool Window::InvalidateByForeignEditView(EditView* ) +{ + return false; +} + void Window::PixelInvalidate(const tools::Rectangle* pRectangle) { if (comphelper::LibreOfficeKit::isDialogPainting() || !comphelper::LibreOfficeKit::isActive()) |