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;
         }

Reply via email to