sw/inc/viscrs.hxx                 |    2 +-
 sw/source/core/crsr/viscrs.cxx    |   19 +------------------
 sw/source/uibase/wrtsh/wrtsh4.cxx |   31 +++++++++++++++++++++++++++++--
 3 files changed, 31 insertions(+), 21 deletions(-)

New commits:
commit 53d2155bce08506c8d4f3faa052cee5ff1f689cf
Author:     Gökay Şatır <[email protected]>
AuthorDate: Mon Mar 2 16:46:04 2026 +0300
Commit:     Miklos Vajna <[email protected]>
CommitDate: Wed Mar 4 08:28:34 2026 +0100

    Writer: Fix empty selection callback.
    
    Issue: When selecting words using CTRL+Mouse click, core side needs to send 
the selection rectangles to Online side.
    Rectangles are not sent but an empty message.
    
    Fix: Aggregate selection rectangles from all cursors in the ring.
    In add mode (CTRL+click multi-selection), the actual selections
    are stored in ring cursors, while m_pCurrentCursor may be empty.
    Without aggregation, callback only reads from m_pCurrentCursor and sends an 
empty payload,
    clearing the selection on the online side.
    
    Signed-off-by: Gökay Şatır <[email protected]>
    Change-Id: I9af5d850ab59644f56358a9ecc5985b2ad529619
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/200830
    Reviewed-by: Miklos Vajna <[email protected]>
    Tested-by: Jenkins CollaboraOffice <[email protected]>

diff --git a/sw/inc/viscrs.hxx b/sw/inc/viscrs.hxx
index 66c7df3387bb..4f4ae8d06fc0 100644
--- a/sw/inc/viscrs.hxx
+++ b/sw/inc/viscrs.hxx
@@ -138,7 +138,7 @@ public:
     static void Get1PixelInLogic( const SwViewShell& rSh,
                                     tools::Long* pX = nullptr, tools::Long* pY 
= nullptr );
 
-    std::optional<OString> getLOKPayload(int nType, int nViewId) const;
+    std::optional<OString> getLOKPayload(int nType) const;
 };
 
 /// Represents the current text cursor of one opened edit window.
diff --git a/sw/source/core/crsr/viscrs.cxx b/sw/source/core/crsr/viscrs.cxx
index 150be2666e82..a5a0e1baf659 100644
--- a/sw/source/core/crsr/viscrs.cxx
+++ b/sw/source/core/crsr/viscrs.cxx
@@ -530,7 +530,7 @@ void SwSelPaintRects::Show(std::vector<OString>* 
pSelectionRectangles)
         pSelectionRectangles->push_back(sRect);
 }
 
-std::optional<OString> SwSelPaintRects::getLOKPayload(int nType, int nViewId) 
const
+std::optional<OString> SwSelPaintRects::getLOKPayload(int nType) const
 {
     switch( nType )
     {
@@ -564,23 +564,6 @@ std::optional<OString> SwSelPaintRects::getLOKPayload(int 
nType, int nViewId) co
             }
         }
         break;
-        case LOK_CALLBACK_TEXT_SELECTION:
-        case LOK_CALLBACK_TEXT_VIEW_SELECTION:
-        {
-            std::vector<OString> aRect;
-            aRect.reserve(size());
-            for (size_type i = 0; i < size(); ++i)
-            {
-                const SwRect& rRect = (*this)[i];
-                aRect.push_back(rRect.SVRect().toString());
-            }
-            OString sRect = comphelper::string::join("; ", aRect);
-            if( nType == LOK_CALLBACK_TEXT_SELECTION )
-                return sRect;
-            else // LOK_CALLBACK_TEXT_VIEW_SELECTION
-                return 
SfxLokHelper::makePayloadJSON(GetShell()->GetSfxViewShell(), nViewId, 
"selection", sRect);
-        }
-        break;
     }
     abort();
 }
diff --git a/sw/source/uibase/wrtsh/wrtsh4.cxx 
b/sw/source/uibase/wrtsh/wrtsh4.cxx
index 0442e3152bb6..7e7591c950c0 100644
--- a/sw/source/uibase/wrtsh/wrtsh4.cxx
+++ b/sw/source/uibase/wrtsh/wrtsh4.cxx
@@ -18,8 +18,11 @@
  */
 
 #include <wrtsh.hxx>
+#include <viscrs.hxx>
 
 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
+#include <comphelper/string.hxx>
+#include <sfx2/lokhelper.hxx>
 
 // Private methods, which move the cursor over search.
 // The removal of the selection must be made on the level above.
@@ -242,10 +245,34 @@ std::optional<OString> SwWrtShell::getLOKPayload(int 
nType, int nViewId) const
         case LOK_CALLBACK_INVALIDATE_VIEW_CURSOR:
             return GetVisibleCursor()->getLOKPayload(nType, nViewId);
         case LOK_CALLBACK_TEXT_SELECTION:
+        case LOK_CALLBACK_TEXT_VIEW_SELECTION:
+        {
+            // Aggregate selection rectangles from all cursors in the ring.
+            // In add mode (CTRL+click multi-selection), the actual selections
+            // are stored in ring cursors, while m_pCurrentCursor may be empty.
+            // Without aggregation, callback only reads from m_pCurrentCursor 
and send an empty payload,
+            // clearing the selection on the online side.
+            std::vector<OString> aAllRects;
+            for (const SwPaM& rPaM : GetCursor_()->GetRingContainer())
+            {
+                const SwShellCursor* pShCursor = dynamic_cast<const 
SwShellCursor*>(&rPaM);
+                if (!pShCursor)
+                    continue;
+                for (size_t i = 0; i < pShCursor->size(); ++i)
+                {
+                    const SwRect& rRect = (*pShCursor)[i];
+                    aAllRects.push_back(rRect.SVRect().toString());
+                }
+            }
+            OString sRect = comphelper::string::join("; ", aAllRects);
+            if (nType == LOK_CALLBACK_TEXT_SELECTION)
+                return sRect;
+            else // LOK_CALLBACK_TEXT_VIEW_SELECTION
+                return SfxLokHelper::makePayloadJSON(GetSfxViewShell(), 
nViewId, "selection", sRect);
+        }
         case LOK_CALLBACK_TEXT_SELECTION_START:
         case LOK_CALLBACK_TEXT_SELECTION_END:
-        case LOK_CALLBACK_TEXT_VIEW_SELECTION:
-            return GetCursor_()->getLOKPayload(nType, nViewId);
+            return GetCursor_()->getLOKPayload(nType);
     }
     abort();
 }

Reply via email to