sw/inc/IDocumentTimerAccess.hxx | 4 -- sw/inc/doc.hxx | 2 - sw/qa/extras/tiledrendering/tiledrendering2.cxx | 37 +++++++++++++++++------- sw/source/core/doc/DocumentTimerManager.cxx | 10 ------ sw/source/core/inc/DocumentTimerManager.hxx | 2 - sw/source/core/inc/frame.hxx | 8 ++--- sw/source/core/layout/layact.cxx | 8 ++++- 7 files changed, 39 insertions(+), 32 deletions(-)
New commits: commit 77b94fd4906f4a2c0b04e0f89ddbc927ac06b4ec Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Thu May 8 08:48:18 2025 +0200 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Thu May 8 13:31:06 2025 +0200 cool#11785 sw lok: take visible area into account when running idle jobs Load a Writer document that is large enough that loading takes more than a second, then spellcheck will be done for the entire document in LOK mode, and only then we'll render the first tile. This was like this since commit 6a490e8834b276359b9ada2ebc95bc86a2dbe759 (cool#11785 sw lok: only start idling after the idle jobs timer stopped, 2025-04-29), previously we always did a full spellcheck after load, before rendering a first tile. Fix the problem by reverting the previous fix (that restored a 1 sec window in time to rendere first tiles) and instead improve SwLayIdle::DoIdleJob(), so in case it wants to only do a job for the visible area, then it takes the LOK visible area into account, similar to how idle layout does this in SwLayIdle::DoIdleJob(). This probably means m_aFireIdleJobsTimer can be fully removed in the future, but that's not yet done here. Change-Id: I676137daf78cb4fd3be90f474e60213846908fef Reviewed-on: https://gerrit.libreoffice.org/c/core/+/185044 Tested-by: Jenkins Reviewed-by: Miklos Vajna <vmik...@collabora.com> diff --git a/sw/inc/IDocumentTimerAccess.hxx b/sw/inc/IDocumentTimerAccess.hxx index 6ccb4c7efc14..5cfb1a3ecc41 100644 --- a/sw/inc/IDocumentTimerAccess.hxx +++ b/sw/inc/IDocumentTimerAccess.hxx @@ -19,8 +19,6 @@ #pragma once -class Timer; - /** * Handle the background jobs of a Writer document. * @@ -71,8 +69,6 @@ public: */ virtual bool IsIdlingBlocked() const = 0; - virtual Timer& GetFireIdleJobsTimer() = 0; - protected: virtual ~IDocumentTimerAccess(){}; }; diff --git a/sw/inc/doc.hxx b/sw/inc/doc.hxx index 837359fbffaf..8e599232aedb 100644 --- a/sw/inc/doc.hxx +++ b/sw/inc/doc.hxx @@ -547,7 +547,7 @@ public: // IDocumentTimerAccess // Our own 'IdleTimer' calls the following method IDocumentTimerAccess const & getIDocumentTimerAccess() const; - SW_DLLPUBLIC IDocumentTimerAccess & getIDocumentTimerAccess(); + IDocumentTimerAccess & getIDocumentTimerAccess(); // IDocumentChartDataProviderAccess IDocumentChartDataProviderAccess const & getIDocumentChartDataProviderAccess() const; diff --git a/sw/qa/extras/tiledrendering/tiledrendering2.cxx b/sw/qa/extras/tiledrendering/tiledrendering2.cxx index 50a3e18a8a68..0960b374220b 100644 --- a/sw/qa/extras/tiledrendering/tiledrendering2.cxx +++ b/sw/qa/extras/tiledrendering/tiledrendering2.cxx @@ -191,11 +191,7 @@ CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testAsyncLayout) CPPUNIT_ASSERT(pPage2->IsInvalidContent()); CPPUNIT_ASSERT(pPage3->IsInvalidContent()); - // And when processing all idle events: - SwDoc* pDoc = pDocShell->GetDoc(); - IDocumentTimerAccess& rIDTA = pDoc->getIDocumentTimerAccess(); - rIDTA.GetFireIdleJobsTimer().Stop(); - rIDTA.StartIdling(); + // And then processing all idle events: Scheduler::ProcessEventsToIdle(); // Then make sure all pages get an async layout: @@ -735,11 +731,6 @@ CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testCommentsOnLoad) // When getting the list of comments from the document + listening for notifications from idle // layout: pXTextDocument->getPostIts(aWriter); - SwDocShell* pDocShell = getSwDocShell(); - SwDoc* pDoc = pDocShell->GetDoc(); - IDocumentTimerAccess& rIDTA = pDoc->getIDocumentTimerAccess(); - rIDTA.GetFireIdleJobsTimer().Stop(); - rIDTA.StartIdling(); Scheduler::ProcessEventsToIdle(); // Then make sure that: @@ -761,6 +752,32 @@ CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testCommentsOnLoad) auto aAction = aView.m_aComment.get_child("action").get_value<std::string>(); CPPUNIT_ASSERT_EQUAL(std::string("Add"), aAction); } + +CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testSpellcheckVisibleArea) +{ + // Given a document with 3 pages, the first page is visible: + OUString aURL = createFileURL(u"3pages.odt"); + UnoApiXmlTest::loadFromURL(aURL); + SwDocShell* pDocShell = getSwDocShell(); + SwWrtShell* pWrtShell = pDocShell->GetWrtShell(); + SwRootFrame* pLayout = pWrtShell->GetLayout(); + SwPageFrame* pPage1 = pLayout->GetLower()->DynCastPageFrame(); + pWrtShell->setLOKVisibleArea(pPage1->getFrameArea().SVRect()); + pPage1->InvalidateAll(); + SwPageFrame* pPage2 = pPage1->GetNext()->DynCastPageFrame(); + pPage2->InvalidateAll(); + SwPageFrame* pPage3 = pPage2->GetNext()->DynCastPageFrame(); + pPage3->InvalidateAll(); + + // When doing idle layout and it's interrupted: + AnyInputCallback aAnyInput; + pWrtShell->LayoutIdle(); + + // Then make sure the visible area is spellchecked, but not the rest: + CPPUNIT_ASSERT(!pPage1->IsInvalidSpelling()); + CPPUNIT_ASSERT(pPage2->IsInvalidSpelling()); + CPPUNIT_ASSERT(pPage3->IsInvalidSpelling()); +} } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/core/doc/DocumentTimerManager.cxx b/sw/source/core/doc/DocumentTimerManager.cxx index c24b2204fb66..df232238eca0 100644 --- a/sw/source/core/doc/DocumentTimerManager.cxx +++ b/sw/source/core/doc/DocumentTimerManager.cxx @@ -56,11 +56,6 @@ DocumentTimerManager::DocumentTimerManager(SwDoc& i_rSwdoc) void DocumentTimerManager::StartIdling() { - if (m_aFireIdleJobsTimer.IsActive()) - { - return; - } - if (m_bWaitForLokInit && comphelper::LibreOfficeKit::isActive()) { // Start the idle jobs only after a certain delay. @@ -107,11 +102,6 @@ void DocumentTimerManager::UnblockIdling() } } -Timer& DocumentTimerManager::GetFireIdleJobsTimer() -{ - return m_aFireIdleJobsTimer; -} - IMPL_LINK(DocumentTimerManager, FireIdleJobsTimeout, Timer*, , void) { // Now we can run the idle jobs, assuming we finished LOK initialization. diff --git a/sw/source/core/inc/DocumentTimerManager.hxx b/sw/source/core/inc/DocumentTimerManager.hxx index 20a9cd83a222..d22852b910bb 100644 --- a/sw/source/core/inc/DocumentTimerManager.hxx +++ b/sw/source/core/inc/DocumentTimerManager.hxx @@ -57,8 +57,6 @@ public: bool IsIdlingBlocked() const override; - Timer& GetFireIdleJobsTimer() override; - private: DocumentTimerManager(DocumentTimerManager const&) = delete; DocumentTimerManager& operator=(DocumentTimerManager const&) = delete; diff --git a/sw/source/core/inc/frame.hxx b/sw/source/core/inc/frame.hxx index 754083f9d27c..1f0354f2a085 100644 --- a/sw/source/core/inc/frame.hxx +++ b/sw/source/core/inc/frame.hxx @@ -157,9 +157,9 @@ private: protected: // write access to mb*Valid flags - void setFrameAreaPositionValid(bool bNew); - void setFrameAreaSizeValid(bool bNew); - void setFramePrintAreaValid(bool bNew); + SW_DLLPUBLIC void setFrameAreaPositionValid(bool bNew); + SW_DLLPUBLIC void setFrameAreaSizeValid(bool bNew); + SW_DLLPUBLIC void setFramePrintAreaValid(bool bNew); public: SwFrameAreaDefinition(); @@ -848,7 +848,7 @@ public: inline void InvalidateAll(); void ImplInvalidateSize(); void ImplInvalidatePrt(); - void ImplInvalidatePos(); + SW_DLLPUBLIC void ImplInvalidatePos(); void ImplInvalidateLineNum(); inline void InvalidateNextPos( bool bNoFootnote = false ); diff --git a/sw/source/core/layout/layact.cxx b/sw/source/core/layout/layact.cxx index bd4c099014d9..0d6cdb0842b2 100644 --- a/sw/source/core/layout/layact.cxx +++ b/sw/source/core/layout/layact.cxx @@ -2321,8 +2321,14 @@ bool SwLayIdle::DoIdleJob(IdleJobType eJob, IdleJobArea eJobArea) } pPage = static_cast<SwPageFrame*>(pPage->GetNext()); + // LOK case: VisArea() is the entire document and getLOKVisibleArea() may contain the actual + // visible area. + const SwRect &rVisArea = m_pImp->GetShell().VisArea(); + SwRect aLokVisArea(m_pImp->GetShell().getLOKVisibleArea()); + bool bUseLokVisArea = comphelper::LibreOfficeKit::isActive() && !aLokVisArea.IsEmpty(); + const SwRect& rVis = bUseLokVisArea ? aLokVisArea : rVisArea; if (pPage && eJobArea == IdleJobArea::VISIBLE && - !pPage->getFrameArea().Overlaps( m_pImp->GetShell().VisArea())) + !pPage->getFrameArea().Overlaps(rVis)) { break; }