summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--editeng/source/editeng/editview.cxx5
-rw-r--r--include/vcl/window.hxx2
-rw-r--r--sc/qa/unit/tiledrendering/tiledrendering.cxx115
-rw-r--r--sc/source/ui/inc/gridwin.hxx1
-rw-r--r--sc/source/ui/view/gridwin4.cxx26
-rw-r--r--vcl/source/window/paint.cxx5
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())