sw/inc/crsrsh.hxx | 2 ++ sw/source/core/crsr/crsrsh.cxx | 9 ++++++++- sw/source/uibase/docvw/edtwin.cxx | 7 ++++++- sw/source/uibase/inc/wrtsh.hxx | 1 + sw/source/uibase/wrtsh/wrtsh1.cxx | 11 ++++++++++- 5 files changed, 27 insertions(+), 3 deletions(-)
New commits: commit 12f6f48303348c5bfdffffa6ef03c5aedeffeeb4 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 24 13:45:48 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) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/137987 Tested-by: Jenkins Reviewed-by: Michael Stahl <michael.st...@allotropia.de> (cherry picked from commit 581ba395222e04e43697484bef9181c877d1fd61) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138027 Reviewed-by: Thorsten Behrens <thorsten.behr...@allotropia.de> (cherry picked from commit d7a427d9c869729c21285df7c32106f934f66a04) Change-Id: Ief176b54daf96da378d2e5d57f3dd5b4a0817299 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138737 Tested-by: Michael Stahl <michael.st...@allotropia.de> Reviewed-by: Michael Stahl <michael.st...@allotropia.de> diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx index 2fa79345b240..b6173fdee6f0 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; @@ -437,6 +438,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 0d8d273f34be..bf3f1718e67c 100644 --- a/sw/source/core/crsr/crsrsh.cxx +++ b/sw/source/core/crsr/crsrsh.cxx @@ -2244,7 +2244,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 7714bdd772d3..c6e5cbda9cbf 100644 --- a/sw/source/uibase/docvw/edtwin.cxx +++ b/sw/source/uibase/docvw/edtwin.cxx @@ -163,6 +163,9 @@ #include <sfx2/event.hxx> #include <memory> +#include "../../core/crsr/callnk.hxx" + + using namespace sw::mark; using namespace ::com::sun::star; @@ -6316,13 +6319,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(); return Selection(sal_Int32(nPos - nStartPos), sal_Int32(nPos - nStartPos)); diff --git a/sw/source/uibase/inc/wrtsh.hxx b/sw/source/uibase/inc/wrtsh.hxx index cf780df77cf0..a61b049f5002 100644 --- a/sw/source/uibase/inc/wrtsh.hxx +++ b/sw/source/uibase/inc/wrtsh.hxx @@ -140,6 +140,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 53e8ae7a2fbd..c240c630df3a 100644 --- a/sw/source/uibase/wrtsh/wrtsh1.cxx +++ b/sw/source/uibase/wrtsh/wrtsh1.cxx @@ -118,6 +118,9 @@ #include <comphelper/lok.hxx> #include <memory> +#include "../../core/crsr/callnk.hxx" + + using namespace sw::mark; using namespace com::sun::star; namespace { @@ -1730,7 +1733,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() ) { m_fnSetCursor = &SwWrtShell::SetCursorKillSel;