From 0a32630d11ebdb8b8218faa066c72582ef2f300d Mon Sep 17 00:00:00 2001 From: Miklos Vajna Date: Tue, 18 May 2021 14:33:53 +0200 Subject: sw: fix not needed invalidation of title field on each keypress Type a character, SwDocShell::DoFlushDocInfo() is called because the number of characters changed, and that rapaints all title fields. This happens as SwFormatField::UpdateTextNode() calls SwTextField::ExpandTextField() with bForceNotify=true, because that was needed for conditional text in commit cd94a84b89c476760ad74bf088a5d6f8ba4ce209 (125044: - use field's content cache on construction only, 2014-06-13). Fix the problem by not forcing notifications for title fields in SwFormatField::UpdateTextNode(): SwTextField::ExpandTextField() will send a notification if the expend result differs without forcing as well. Change-Id: I5e46ab6aef33ff5e348d40b8644bcc9cf353c326 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/115743 Reviewed-by: Miklos Vajna Tested-by: Jenkins --- .../core/txtnode/data/title-field-invalidate.fodt | 23 +++++++ sw/qa/core/txtnode/txtnode.cxx | 70 ++++++++++++++++++++++ sw/source/core/txtnode/atrfld.cxx | 19 +++++- 3 files changed, 111 insertions(+), 1 deletion(-) create mode 100644 sw/qa/core/txtnode/data/title-field-invalidate.fodt (limited to 'sw') diff --git a/sw/qa/core/txtnode/data/title-field-invalidate.fodt b/sw/qa/core/txtnode/data/title-field-invalidate.fodt new file mode 100644 index 000000000000..e47129538fa9 --- /dev/null +++ b/sw/qa/core/txtnode/data/title-field-invalidate.fodt @@ -0,0 +1,23 @@ + + + + mytitle + + + + + + + + + + mytitle + + + + + + body text + + + diff --git a/sw/qa/core/txtnode/txtnode.cxx b/sw/qa/core/txtnode/txtnode.cxx index a4c7baed8492..f4bb070ac972 100644 --- a/sw/qa/core/txtnode/txtnode.cxx +++ b/sw/qa/core/txtnode/txtnode.cxx @@ -9,8 +9,13 @@ #include +#include +#include +#include #include +#include +#include #include #include #include @@ -84,6 +89,71 @@ CPPUNIT_TEST_FIXTURE(SwCoreTxtnodeTest, testTextBoxNodeSplit) pWrtShell->SplitNode(); } +namespace +{ +struct ViewCallback +{ + int m_nInvalidations = 0; + + static void callback(int nType, const char* pPayload, void* pData); + void callbackImpl(int nType, const char* pPayload); +}; + +void ViewCallback::callback(int nType, const char* pPayload, void* pData) +{ + static_cast(pData)->callbackImpl(nType, pPayload); +} + +void ViewCallback::callbackImpl(int nType, const char* /*pPayload*/) +{ + switch (nType) + { + case LOK_CALLBACK_INVALIDATE_TILES: + { + ++m_nInvalidations; + } + break; + } +} +} + +CPPUNIT_TEST_FIXTURE(SwCoreTxtnodeTest, testTitleFieldInvalidate) +{ + // Set up LOK to track invalidations. + comphelper::LibreOfficeKit::setActive(true); + + // Given a document with a title field: + load(DATA_DIRECTORY, "title-field-invalidate.fodt"); + SwXTextDocument* pTextDoc = dynamic_cast(mxComponent.get()); + pTextDoc->initializeForTiledRendering({}); + SwDocShell* pShell = pTextDoc->GetDocShell(); + SwDoc* pDoc = pShell->GetDoc(); + SwWrtShell* pWrtShell = pShell->GetWrtShell(); + pWrtShell->SttEndDoc(/*bStt=*/false); + ViewCallback aCallback; + pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, + &aCallback); + Scheduler::ProcessEventsToIdle(); + aCallback.m_nInvalidations = 0; + + // When typing to the document: + pWrtShell->Insert("x"); + + // Then make sure that only the text frame at the cursor is invalidated: + pDoc->getIDocumentStatistics().GetUpdatedDocStat(/*bCompleteAsync=*/true, /*bFields=*/false); + // Without the accompanying fix in place, this test would have failed with: + // - Expected: 1 + // - Actual : 2 + // i.e. the footer was also invalidated on each keypress. + CPPUNIT_ASSERT_EQUAL(1, aCallback.m_nInvalidations); + + // Tear down LOK. + pWrtShell->GetSfxViewShell()->registerLibreOfficeKitViewCallback(nullptr, nullptr); + mxComponent->dispose(); + mxComponent.clear(); + comphelper::LibreOfficeKit::setActive(false); +} + CPPUNIT_PLUGIN_IMPLEMENT(); /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/core/txtnode/atrfld.cxx b/sw/source/core/txtnode/atrfld.cxx index 558874ad1784..089f35c188d6 100644 --- a/sw/source/core/txtnode/atrfld.cxx +++ b/sw/source/core/txtnode/atrfld.cxx @@ -377,7 +377,24 @@ void SwFormatField::UpdateTextNode(const SfxPoolItem* pOld, const SfxPoolItem* p pTextNd->TriggerNodeUpdate(sw::LegacyModifyHint(pNodeOld, pNodeNew)); if(bExpand) { - mpTextField->ExpandTextField( pOld == nullptr && pNew == nullptr ); + bool bForceNotify = pOld == nullptr && pNew == nullptr; + if (bForceNotify) + { + // Force notify was added for conditional text fields, at least the title fields needs + // no forced notify. + const SwField* pField = mpTextField->GetFormatField().GetField(); + const SwFieldIds nWhich = pField->GetTyp()->Which(); + if (nWhich == SwFieldIds::DocInfo) + { + auto pDocInfoField = static_cast(pField); + if (pDocInfoField->GetSubType() == nsSwDocInfoSubType::DI_TITLE) + { + bForceNotify = false; + } + } + } + + mpTextField->ExpandTextField(bForceNotify); } } -- cgit v1.2.1