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