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 3b2ab404e21b648ddc9761c175dadb32b6459364
Author:     Miklos Vajna <[email protected]>
AuthorDate: Thu Dec 4 08:27:37 2025 +0100
Commit:     Miklos Vajna <[email protected]>
CommitDate: Fri Dec 5 09:28:15 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/+/195013
    Tested-by: Jenkins
    Reviewed-by: Miklos Vajna <[email protected]>

diff --git a/sw/inc/view.hxx b/sw/inc/view.hxx
index 58dfe749b1cf..eaf65e7637d2 100644
--- a/sw/inc/view.hxx
+++ b/sw/inc/view.hxx
@@ -752,6 +752,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 0f699341829e..ff6e777d1325 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/XLayoutManager.hpp>
 #include <com/sun/star/frame/XDispatchHelper.hpp>
@@ -467,6 +471,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 b0a11e7e6939..855712b00d91 100644
--- a/sw/source/uibase/uiview/view.cxx
+++ b/sw/source/uibase/uiview/view.cxx
@@ -2173,6 +2173,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