diff --git a/sd/qa/unit/tiledrendering/tiledrendering.cxx b/sd/qa/unit/tiledrendering/tiledrendering.cxx index a80a8de2e9c1..28e0ac8043a8 100644 --- a/sd/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx @@ -71,6 +71,7 @@ public: void testViewLock(); void testUndoLimiting(); void testCreateViewGraphicSelection(); + void testCreateViewTextCursor(); CPPUNIT_TEST_SUITE(SdTiledRenderingTest); CPPUNIT_TEST(testRegisterCallback); @@ -97,6 +98,7 @@ public: CPPUNIT_TEST(testViewLock); CPPUNIT_TEST(testUndoLimiting); CPPUNIT_TEST(testCreateViewGraphicSelection); + CPPUNIT_TEST(testCreateViewTextCursor); CPPUNIT_TEST_SUITE_END(); private: @@ -870,6 +872,8 @@ public: bool m_bCursorVisibleChanged; bool m_bViewLock; bool m_bTilesInvalidated; + std::map m_aViewCursorInvalidations; + std::map m_aViewCursorVisibilities; ViewCallback() : m_bGraphicSelectionInvalidated(false), @@ -923,6 +927,24 @@ public: m_bViewLock = aTree.get_child("rectangle").get_value() != "EMPTY"; } break; + case LOK_CALLBACK_INVALIDATE_VIEW_CURSOR: + { + std::stringstream aStream(pPayload); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + int nViewId = aTree.get_child("viewId").get_value(); + m_aViewCursorInvalidations[nViewId] = true; + } + break; + case LOK_CALLBACK_VIEW_CURSOR_VISIBLE: + { + std::stringstream aStream(pPayload); + boost::property_tree::ptree aTree; + boost::property_tree::read_json(aStream, aTree); + int nViewId = aTree.get_child("viewId").get_value(); + m_aViewCursorVisibilities[nViewId] = OString("true") == pPayload; + } + break; } } }; @@ -1152,6 +1174,53 @@ void SdTiledRenderingTest::testCreateViewGraphicSelection() comphelper::LibreOfficeKit::setActive(false); } +void SdTiledRenderingTest::testCreateViewTextCursor() +{ + comphelper::LibreOfficeKit::setActive(); + + // Load a document and register a callback. + SdXImpressDocument* pXImpressDocument = createDoc("title-shape.odp"); + ViewCallback aView1; + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView1); + + // Begin text edit. + pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB); + pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB); + pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); + pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); + Scheduler::ProcessEventsToIdle(); + sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell(); + SdrView* pSdrView = pViewShell->GetView(); + CPPUNIT_ASSERT(pSdrView->IsTextEdit()); + + // Make sure that creating a new view either doesn't affect the previous + // one, or at least the effect is not visible at the end. + aView1.m_aViewCursorInvalidations.clear(); + aView1.m_aViewCursorVisibilities.clear(); + SfxLokHelper::createView(); + pXImpressDocument->initializeForTiledRendering({}); + ViewCallback aView2; + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView2); + bool bFoundCursor = false; + for (const auto& rInvalidation : aView1.m_aViewCursorInvalidations) + { + auto itVisibility = aView1.m_aViewCursorVisibilities.find(rInvalidation.first); + // For each cursor invalidation: if there is no visibility or the visibility is true, that's a problem. + if (itVisibility == aView1.m_aViewCursorVisibilities.end() || (itVisibility != aView1.m_aViewCursorVisibilities.end() && itVisibility->second)) + { + bFoundCursor = true; + break; + } + } + // This failed: the second view created an unexpected view cursor in the + // first view. + CPPUNIT_ASSERT(!bFoundCursor); + + mxComponent->dispose(); + mxComponent.clear(); + comphelper::LibreOfficeKit::setActive(false); +} + CPPUNIT_TEST_SUITE_REGISTRATION(SdTiledRenderingTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/svx/source/svdraw/svdedxv.cxx b/svx/source/svdraw/svdedxv.cxx index 323b4a869183..c06c22ee41ee 100644 --- a/svx/source/svdraw/svdedxv.cxx +++ b/svx/source/svdraw/svdedxv.cxx @@ -158,6 +158,7 @@ SdrPageView* SdrObjEditView::ShowSdrPage(SdrPage* pPage) // registers the view shell of this draw view, and not the view // shell of pView. OutlinerView* pOutlinerView = pView->ImpMakeOutlinerView(static_cast(pOutDev), !bEmpty, nullptr, GetSfxViewShell()); + pOutlinerView->HideCursor(); pView->GetTextEditOutliner()->InsertView(pOutlinerView); } } @@ -911,6 +912,7 @@ bool SdrObjEditView::SdrBeginTextEdit( if(&rOutDev != pWin && OUTDEV_WINDOW == rOutDev.GetOutDevType()) { OutlinerView* pOutlView = ImpMakeOutlinerView(static_cast(&rOutDev), !bEmpty, nullptr); + pOutlView->HideCursor(); pTextEditOutliner->InsertView(pOutlView); } }