diff options
author | Michael Stahl <michael.stahl@allotropia.de> | 2022-08-08 16:15:36 +0200 |
---|---|---|
committer | Thorsten Behrens <thorsten.behrens@allotropia.de> | 2022-08-30 10:46:04 +0200 |
commit | 0b8ce1c0e9606971882acb00fa826ab5cc194cb4 (patch) | |
tree | 95a2cd05ae865c9cfccb6678808466c72b238faa /sw | |
parent | 188555883266b661ec201548bc4b4ccd01460862 (diff) |
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.stahl@allotropia.de>
(cherry picked from commit 581ba395222e04e43697484bef9181c877d1fd61)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138027
Reviewed-by: Thorsten Behrens <thorsten.behrens@allotropia.de>
(cherry picked from commit d7a427d9c869729c21285df7c32106f934f66a04)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/138548
Diffstat (limited to 'sw')
-rw-r--r-- | sw/inc/crsrsh.hxx | 2 | ||||
-rw-r--r-- | sw/source/core/crsr/crsrsh.cxx | 9 | ||||
-rw-r--r-- | sw/source/uibase/docvw/edtwin.cxx | 5 | ||||
-rw-r--r-- | sw/source/uibase/inc/wrtsh.hxx | 1 | ||||
-rw-r--r-- | sw/source/uibase/wrtsh/wrtsh1.cxx | 9 |
5 files changed, 23 insertions, 3 deletions
diff --git a/sw/inc/crsrsh.hxx b/sw/inc/crsrsh.hxx index 6d843e7e424d..e906d732256e 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; @@ -434,6 +435,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 ae7b2c81133d..8145d938752f 100644 --- a/sw/source/core/crsr/crsrsh.cxx +++ b/sw/source/core/crsr/crsrsh.cxx @@ -2260,7 +2260,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 4898ba948f4e..c013c002cca0 100644 --- a/sw/source/uibase/docvw/edtwin.cxx +++ b/sw/source/uibase/docvw/edtwin.cxx @@ -140,6 +140,7 @@ #include <sfx2/event.hxx> #include <memory> +#include "../../core/crsr/callnk.hxx" #include <IDocumentOutlineNodes.hxx> #include <ndtxt.hxx> #include <cntfrm.hxx> @@ -6479,13 +6480,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 a4ba598df693..491373236b61 100644 --- a/sw/source/uibase/inc/wrtsh.hxx +++ b/sw/source/uibase/inc/wrtsh.hxx @@ -143,6 +143,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 3fb293405387..955d9d280583 100644 --- a/sw/source/uibase/wrtsh/wrtsh1.cxx +++ b/sw/source/uibase/wrtsh/wrtsh1.cxx @@ -104,6 +104,7 @@ #include <comphelper/propertyvalue.hxx> #include <memory> +#include "../../core/crsr/callnk.hxx" #include <frmtool.hxx> #include <viewopt.hxx> @@ -1853,7 +1854,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()) |