sw/inc/crsrsh.hxx | 2 ++ sw/source/core/crsr/crsrsh.cxx | 9 ++++++++- sw/source/uibase/docvw/edtwin.cxx | 5 ++++- sw/source/uibase/inc/wrtsh.hxx | 1 + sw/source/uibase/wrtsh/wrtsh1.cxx | 9 ++++++++- 5 files changed, 23 insertions(+), 3 deletions(-)
New commits: commit 581ba395222e04e43697484bef9181c877d1fd61 Author: Michael Stahl <michael.st...@allotropia.de> AuthorDate: Mon Aug 8 16:15:36 2022 +0200 Commit: Michael Stahl <michael.st...@allotropia.de> CommitDate: Wed Aug 10 10:57:00 2022 +0200 sw: fix infinite recursion in SwEditWin::GetSurroundingTextSelection() The unexpected problem of calling SwCursorShell::Pop() from there ending up calling the function itself again, with gtk3 UI, on loading forum-mso-en-4034.docx and clicking somewhere or scrolling: 466 SwEditWin::GetSurroundingTextSelection() const at sw/source/uibase/docvw/edtwin.cxx:6656 467 ImplHandleSurroundingTextRequest(vcl::Window*, rtl::OUString&, Selection&) at vcl/source/window/winproc.cxx:2487 468 ImplHandleSalSurroundingTextRequest(vcl::Window*, SalSurroundingTextRequestEvent*) at vcl/source/window/winproc.cxx:2497 469 ImplWindowFrameProc(vcl::Window*, SalEvent, void const*) at vcl/source/window/winproc.cxx:2826 470 SalFrame::CallCallback(SalEvent, void const*) const at vcl/inc/salframe.hxx:306 471 GtkSalFrame::IMHandler::signalIMRetrieveSurrounding(_GtkIMContext*, void*) at vcl/unx/gtk3/gtkframe.cxx:5707 472 _gtk_marshal_BOOLEAN__VOIDv () at /lib64/libgtk-3.so.0 473 g_signal_emit_valist () at /lib64/libgobject-2.0.so.0 474 g_signal_emit_by_name () at /lib64/libgobject-2.0.so.0 475 gtk_im_multicontext_retrieve_surrounding_cb () at /lib64/libgtk-3.so.0 476 _gtk_marshal_BOOLEAN__VOIDv () at /lib64/libgtk-3.so.0 477 g_signal_emit_valist () at /lib64/libgobject-2.0.so.0 478 g_signal_emit_by_name () at /lib64/libgobject-2.0.so.0 479 enable () at /lib64/libgtk-3.so.0 480 GtkSalFrame::IMHandler::createIMContext() at vcl/unx/gtk3/gtkframe.cxx:5187 481 GtkSalFrame::IMHandler::IMHandler(GtkSalFrame*) at vcl/unx/gtk3/gtkframe.cxx:5153 482 GtkSalFrame::SetInputContext(SalInputContext*) at vcl/unx/gtk3/gtkframe.cxx:2711 483 vcl::Window::ImplNewInputContext() () at vcl/source/window/window.cxx:1781 484 vcl::Window::SetInputContext(InputContext const&) at vcl/source/window/window.cxx:2083 485 SwView::CheckReadonlySelection() at sw/source/uibase/uiview/view.cxx:699 486 SwView::AttrChangedNotify(LinkParamNone*) at sw/source/uibase/uiview/view.cxx:510 487 SwView::LinkStubAttrChangedNotify(void*, LinkParamNone*) at sw/source/uibase/uiview/view.cxx:499 488 Link<LinkParamNone*, void>::Call(LinkParamNone*) const at include/tools/link.hxx:111 489 SwCursorShell::CallChgLnk() at sw/source/core/crsr/crsrsh.cxx:2544 490 SwCallLink::~SwCallLink() at sw/source/core/crsr/callnk.cxx:149 491 SwCursorShell::Pop(SwCursorShell::PopMode) at sw/source/core/crsr/crsrsh.cxx:2327 492 SwWrtShell::Pop(SwCursorShell::PopMode) at sw/source/uibase/wrtsh/wrtsh1.cxx:2016 493 SwEditWin::GetSurroundingTextSelection() const at sw/source/uibase/docvw/edtwin.cxx:6656 This SwCallLink looks unnecessary here, but it's triggered because it compares the state before Pop() to the state after Pop(), instead of the state before Push() to the state after Pop(). This problem could probably benefit from being solved more generally, but with 2 functions involved it gets rather ugly as it can't easily be encapsulated in SwCursorShell. (probably regression from aac9bd235e65b27faf63e64bba3ecd94837381d6) Change-Id: Ief176b54daf96da378d2e5d57f3dd5b4a0817299 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137987 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@allotropia.de> diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx index 0b66682b9c92..c2a5d75c454c 100644 --- a/sw/inc/crsrsh.hxx +++ b/sw/inc/crsrsh.hxx @@ -45,6 +45,7 @@ class SfxItemSet; class SfxPoolItem; +class SwCallLink; class SwContentFrame; class SwUnoCursor; class SwFormatField; @@ -436,6 +437,7 @@ public: * stack * @return <true> if there was one on the stack, <false> otherwise */ + bool Pop(PopMode, ::std::unique_ptr<SwCallLink> pLink); bool Pop(PopMode); /* * Combine 2 Cursors. diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx index 745fb43f5239..4b7fbcbd377d 100644 --- a/sw/source/core/crsr/crsrsh.cxx +++ b/sw/source/core/crsr/crsrsh.cxx @@ -2268,7 +2268,14 @@ void SwCursorShell::Push() */ bool SwCursorShell::Pop(PopMode const eDelete) { - SwCallLink aLk( *this ); // watch Cursor-Moves; call Link if needed + ::std::unique_ptr<SwCallLink> pLink(::std::make_unique<SwCallLink>(*this)); // watch Cursor-Moves; call Link if needed + return Pop(eDelete, ::std::move(pLink)); +} + +bool SwCursorShell::Pop(PopMode const eDelete, + [[maybe_unused]] ::std::unique_ptr<SwCallLink> const pLink) +{ + assert(pLink); // parameter exists only to be deleted before return // are there any left? if (nullptr == m_pStackCursor) diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx index 359d01ddec40..b796270b9bdc 100644 --- a/sw/source/uibase/docvw/edtwin.cxx +++ b/sw/source/uibase/docvw/edtwin.cxx @@ -145,6 +145,7 @@ #include <sfx2/event.hxx> #include <memory> +#include "../../core/crsr/callnk.hxx" #include <IDocumentOutlineNodes.hxx> #include <ndtxt.hxx> #include <cntfrm.hxx> @@ -6643,13 +6644,15 @@ Selection SwEditWin::GetSurroundingTextSelection() const // around the visible cursor. TextFrameIndex const nPos(rSh.GetCursorPointAsViewIndex()); + // store shell state *before* Push + ::std::unique_ptr<SwCallLink> pLink(::std::make_unique<SwCallLink>(rSh)); rSh.Push(); rSh.HideCursor(); rSh.GoStartSentence(); TextFrameIndex const nStartPos(rSh.GetCursorPointAsViewIndex()); - rSh.Pop(SwCursorShell::PopMode::DeleteCurrent); + rSh.Pop(SwCursorShell::PopMode::DeleteCurrent, ::std::move(pLink)); rSh.ShowCursor(); if (bUnLockView) diff --git a/sw/source/uibase/inc/wrtsh.hxx b/sw/source/uibase/inc/wrtsh.hxx index db1b89822eb3..d8a0e2559624 100644 --- a/sw/source/uibase/inc/wrtsh.hxx +++ b/sw/source/uibase/inc/wrtsh.hxx @@ -146,6 +146,7 @@ public: // is there a text- or frameselection? bool HasSelection() const { return SwCursorShell::HasSelection() || IsMultiSelection() || IsSelFrameMode() || IsObjSelected(); } + bool Pop(SwCursorShell::PopMode, ::std::unique_ptr<SwCallLink> const pLink); bool Pop(SwCursorShell::PopMode = SwCursorShell::PopMode::DeleteStack); void EnterStdMode(); diff --git a/sw/source/uibase/wrtsh/wrtsh1.cxx b/sw/source/uibase/wrtsh/wrtsh1.cxx index aef0dc502e9a..d61cb158c93f 100644 --- a/sw/source/uibase/wrtsh/wrtsh1.cxx +++ b/sw/source/uibase/wrtsh/wrtsh1.cxx @@ -108,6 +108,7 @@ #include <svl/zformat.hxx> #include <memory> +#include "../../core/crsr/callnk.hxx" #include <frmtool.hxx> #include <viewopt.hxx> @@ -2013,7 +2014,13 @@ SwWrtShell::~SwWrtShell() bool SwWrtShell::Pop(SwCursorShell::PopMode const eDelete) { - bool bRet = SwCursorShell::Pop(eDelete); + ::std::unique_ptr<SwCallLink> pLink(::std::make_unique<SwCallLink>(*this)); + return Pop(eDelete, ::std::move(pLink)); +} + +bool SwWrtShell::Pop(SwCursorShell::PopMode const eDelete, ::std::unique_ptr<SwCallLink> pLink) +{ + bool bRet = SwCursorShell::Pop(eDelete, ::std::move(pLink)); if( bRet && IsSelection() ) { if (!IsAddMode())