sw/inc/view.hxx                  |    4 +
 sw/qa/uibase/uiview/uiview.cxx   |   80 +++++++++++++++++++++++++++++++++++++++
 sw/source/uibase/uiview/view.cxx |   13 ++++++
 3 files changed, 97 insertions(+)

New commits:
commit b70fcb660c1b1f92ee76f376e8d6c7b1f79bba79
Author:     Miklos Vajna <[email protected]>
AuthorDate: Thu Dec 4 08:27:37 2025 +0100
Commit:     Miklos Vajna <[email protected]>
CommitDate: Thu Dec 4 11:23:33 2025 +0100

    cool#13574 sw redline render mode: invalidate both omit modes together
    
    The default SwRedlineRenderMode is unchanged, but in case there is a LOK
    invalidate for the "omit deletes" mode, then issue invalidates for both
    "omit insert" (1) and "omit delete" (2).
    
    With this, a LOK client can do paintPartTile() calls in both modes, to
    show the result in parallel.
    
    This works, because the UNO command toggles between "standard" (0) and
    "omit delete", so the additional invalidate we need to generate is "omit
    insert".
    
    Change-Id: If1b809ce32e8b4180765b9a56275cc00e7f255a7
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/194973
    Tested-by: Caolán McNamara <[email protected]>
    Tested-by: Jenkins CollaboraOffice <[email protected]>
    Reviewed-by: Caolán McNamara <[email protected]>

diff --git a/sw/inc/view.hxx b/sw/inc/view.hxx
index f8fa6d4e2cd5..5e900b461a06 100644
--- a/sw/inc/view.hxx
+++ b/sw/inc/view.hxx
@@ -746,6 +746,10 @@ public:
     void BringToAttention(std::vector<basegfx::B2DRange>&& aRanges = {});
     void BringToAttention(const tools::Rectangle& rRect);
     void BringToAttention(const SwNode* pNode);
+
+    /// See SfxViewShell::libreOfficeKitViewInvalidateTilesCallback().
+    void libreOfficeKitViewInvalidateTilesCallback(const tools::Rectangle* 
pRect, int nPart,
+                                                   int nMode) const override;
 };
 
 std::unique_ptr<SfxTabPage> CreatePrintOptionsPage(weld::Container* pPage, 
weld::DialogController* pController,
diff --git a/sw/qa/uibase/uiview/uiview.cxx b/sw/qa/uibase/uiview/uiview.cxx
index 4694c3c6f7bb..96028bc10759 100644
--- a/sw/qa/uibase/uiview/uiview.cxx
+++ b/sw/qa/uibase/uiview/uiview.cxx
@@ -9,6 +9,7 @@
 
 #include <swmodeltestbase.hxx>
 
+#include <LibreOfficeKit/LibreOfficeKitEnums.h>
 #include <comphelper/processfactory.hxx>
 #include <osl/file.hxx>
 #include <comphelper/propertyvalue.hxx>
@@ -16,6 +17,9 @@
 #include <vcl/scheduler.hxx>
 #include <sfx2/viewfrm.hxx>
 #include <sfx2/dispatch.hxx>
+#include <sfx2/lokhelper.hxx>
+#include <test/lokcallback.hxx>
+#include <comphelper/string.hxx>
 
 #include <com/sun/star/frame/XDispatchHelper.hpp>
 #include <com/sun/star/frame/XDispatchProvider.hpp>
@@ -418,6 +422,82 @@ CPPUNIT_TEST_FIXTURE(SwUibaseUiviewTest, 
testRedlineRenderModeCommand)
     CPPUNIT_ASSERT_EQUAL(SwRedlineRenderMode::Standard, eActual);
 }
 
+namespace
+{
+/// LOK view callback for test purposes.
+struct ViewCallback
+{
+    std::set<SwRedlineRenderMode> m_aInvalidationModes;
+
+    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<ViewCallback*>(pData)->callbackImpl(nType, pPayload);
+}
+
+void ViewCallback::callbackImpl(int nType, const char* pPayload)
+{
+    switch (nType)
+    {
+        case LOK_CALLBACK_INVALIDATE_TILES:
+        {
+            OUString aPayload = OUString::fromUtf8(pPayload);
+            if (aPayload.startsWith("EMPTY"))
+            {
+                break;
+            }
+            uno::Sequence<OUString> aSeq = 
comphelper::string::convertCommaSeparated(aPayload);
+            // x y w h part mode
+            CPPUNIT_ASSERT_EQUAL(static_cast<sal_Int32>(6), aSeq.getLength());
+            
m_aInvalidationModes.insert(static_cast<SwRedlineRenderMode>(aSeq[5].toInt32()));
+        }
+        break;
+    }
+}
+}
+
+CPPUNIT_TEST_FIXTURE(SwUibaseUiviewTest, testRedlineRenderModeInvalidate)
+{
+    // Set up LOK:
+    comphelper::LibreOfficeKit::setActive(true);
+    comphelper::LibreOfficeKit::setPartInInvalidation(true);
+
+    // Given a document where redline render mode is set to "omit deletes":
+    createSwDoc();
+    getSwTextDoc()->initializeForTiledRendering({});
+    SwDocShell* pDocShell = getSwDocShell();
+    SwWrtShell* pWrtShell = pDocShell->GetWrtShell();
+    ViewCallback aCallback;
+    TestLokCallbackWrapper aCallbackWrapper(&ViewCallback::callback, 
&aCallback);
+    
pWrtShell->GetSfxViewShell()->setLibreOfficeKitViewCallback(&aCallbackWrapper);
+    
aCallbackWrapper.setLOKViewId(SfxLokHelper::getView(*pWrtShell->GetSfxViewShell()));
+    SwViewOption aOpt(*pWrtShell->GetViewOptions());
+    aOpt.SetRedlineRenderMode(SwRedlineRenderMode::OmitDeletes);
+    pWrtShell->ApplyViewOptions(aOpt);
+    Scheduler::ProcessEventsToIdle();
+    aCallback.m_aInvalidationModes.clear();
+
+    // When typing a key:
+    pWrtShell->Insert(u"x"_ustr);
+    pWrtShell->GetSfxViewShell()->flushPendingLOKInvalidateTiles();
+
+    // Then make sure that both the "omit inserts" and the "omit deletes" 
modes are invalidated:
+    // Without the accompanying fix in place, this test would have failed, 
only the "omit deletes"
+    // mode was invalidated.
+    
CPPUNIT_ASSERT(aCallback.m_aInvalidationModes.contains(SwRedlineRenderMode::OmitInserts));
+    
CPPUNIT_ASSERT(aCallback.m_aInvalidationModes.contains(SwRedlineRenderMode::OmitDeletes));
+
+    // Tear down LOK:
+    pWrtShell->GetSfxViewShell()->setLibreOfficeKitViewCallback(nullptr);
+    mxComponent->dispose();
+    mxComponent.clear();
+    comphelper::LibreOfficeKit::setPartInInvalidation(false);
+    comphelper::LibreOfficeKit::setActive(false);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/uibase/uiview/view.cxx b/sw/source/uibase/uiview/view.cxx
index 80972473c696..13479362ece1 100644
--- a/sw/source/uibase/uiview/view.cxx
+++ b/sw/source/uibase/uiview/view.cxx
@@ -2148,6 +2148,19 @@ IMPL_LINK_NOARG(SwView, BringToAttentionBlinkTimerHdl, 
Timer*, void)
     }
 }
 
+void SwView::libreOfficeKitViewInvalidateTilesCallback(const tools::Rectangle* 
pRect, int nPart,
+                                                       int nMode) const
+{
+    SfxViewShell::libreOfficeKitViewInvalidateTilesCallback(pRect, nPart, 
nMode);
+    if (static_cast<SwRedlineRenderMode>(nMode) == 
SwRedlineRenderMode::OmitDeletes)
+    {
+        // If an "omit deletes" mode is invalidated, also invalidate the 
matching "omit inserts"
+        // mode.
+        SfxViewShell::libreOfficeKitViewInvalidateTilesCallback(
+            pRect, nPart, static_cast<int>(SwRedlineRenderMode::OmitInserts));
+    }
+}
+
 namespace sw {
 
 void InitPrintOptionsFromApplication(SwPrintData & o_rData, bool const bWeb)

Reply via email to