sw/qa/core/objectpositioning/data/as_char_image.docx |binary sw/qa/core/objectpositioning/objectpositioning.cxx | 23 +++++++++++++++++++ sw/source/core/crsr/crsrsh.cxx | 13 ++++++---- sw/source/core/text/itrcrsr.cxx | 7 ++++- 4 files changed, 36 insertions(+), 7 deletions(-)
New commits: commit 3fb0973b7b5620e637c04b067a870fb611be4b35 Author: Jaume Pujantell <jaume.pujant...@collabora.com> AuthorDate: Tue Nov 19 16:26:24 2024 +0100 Commit: Michael Stahl <michael.st...@allotropia.de> CommitDate: Mon Mar 3 12:49:05 2025 +0100 tdf#163890 sw: fix anchor inserted shape to paragraph Since the commit 651527b4efe9700c8c8dff58ce5aa86ad5681f16 "sw: fix double-click opening frame dialog, not graphic dialog on images", when GetModelPositionForViewPoint is called on an "as-char" graphic it returns the graphic node. This makes inserted shapes anchor to page as a fallback since they don't find a text node to anchor to. With this change, the function returns the anchor text node as before if the caller explicitly asks for only text frames. This change breaks testTdf157129 in sw_uiwriter8. After pasting content ending with a hidden paragraph, SwCursorShell::UpdateCursorPos() should only move the cursor outside the hidden content. Before this change, the call to GetLayout()->GetModelPositionForViewPoint didn't change the cursor position because SwTextCursor::GetModelPositionForViewPoint called pFlyPor->GetFlyCursorOfst and returned success even when it failed to get a text node and therefore the cursor didn't change. Now it finds a valid text node and changes the cursor to that. But this is the wrong behavior, GetModelPositionForViewPoint should not be called if a non-hidden paragraph can trivially be found. Change-Id: I8cf9f0c7dcfe6f4be46435c8506e67606ce8fe9c Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176775 Reviewed-by: Miklos Vajna <vmik...@collabora.com> Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> (cherry picked from commit 7ee34038b12c18b34261beb303f1f945d690761c) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/176863 Tested-by: Jenkins (cherry picked from commit dd5f718c4b621313c406ea6ed4d7141b8db78e61) Reviewed-on: https://gerrit.libreoffice.org/c/core/+/182421 Reviewed-by: Michael Stahl <michael.st...@allotropia.de> diff --git a/sw/qa/core/objectpositioning/data/as_char_image.docx b/sw/qa/core/objectpositioning/data/as_char_image.docx new file mode 100644 index 000000000000..e5e02d2168e1 Binary files /dev/null and b/sw/qa/core/objectpositioning/data/as_char_image.docx differ diff --git a/sw/qa/core/objectpositioning/objectpositioning.cxx b/sw/qa/core/objectpositioning/objectpositioning.cxx index 565a3fe4fca6..ae228ebaf7fb 100644 --- a/sw/qa/core/objectpositioning/objectpositioning.cxx +++ b/sw/qa/core/objectpositioning/objectpositioning.cxx @@ -12,6 +12,7 @@ #include <com/sun/star/text/VertOrientation.hpp> #include <com/sun/star/drawing/XDrawPageSupplier.hpp> +#include <comphelper/propertysequence.hxx> #include <editeng/ulspitem.hxx> #include <wrtsh.hxx> @@ -489,6 +490,28 @@ CPPUNIT_TEST_FIXTURE(Test, testDoNotCaptureDrawObjsOnPageDrawWrapNone) // some <1px difference). CPPUNIT_ASSERT_GREATER(nPage2Top - MINFLY, nDrawObjTop); } + +CPPUNIT_TEST_FIXTURE(Test, testInsertShapeOnAsCharImg_tdf16890) +{ + // Given a document with an image anchored as character + createSwDoc("as_char_image.docx"); + SwDoc* pDoc = getSwDoc(); + + // Insert a shape over it + uno::Sequence<beans::PropertyValue> aArgs( + comphelper::InitPropertySequence({ { "KeyModifier", uno::Any(KEY_MOD1) } })); + dispatchCommand(mxComponent, ".uno:BasicShapes.rectangle", aArgs); + + // Check that hte new shape is anchored at para (i.e. has an anchor node) + const auto& rFrmFormats = *pDoc->GetSpzFrameFormats(); + CPPUNIT_ASSERT_EQUAL(size_t(o3tl::make_unsigned(2)), rFrmFormats.size()); + auto pShape = rFrmFormats[1]; + CPPUNIT_ASSERT(pShape); + // Without the accompanying fix in place, this test would have failed with: + // assertion failed + // - Expression: pShape->GetAnchor().GetAnchorNode() + CPPUNIT_ASSERT(pShape->GetAnchor().GetAnchorNode()); +} } CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sw/source/core/crsr/crsrsh.cxx b/sw/source/core/crsr/crsrsh.cxx index f2945f306a2c..54f03657ef53 100644 --- a/sw/source/core/crsr/crsrsh.cxx +++ b/sw/source/core/crsr/crsrsh.cxx @@ -1851,11 +1851,6 @@ void SwCursorShell::UpdateCursorPos() if (isInHiddenFrame(pShellCursor) && !ExtendedSelectedAll()) { - SwCursorMoveState aTmpState(CursorMoveState::SetOnlyText); - aTmpState.m_bSetInReadOnly = IsReadOnlyAvailable(); - GetLayout()->GetModelPositionForViewPoint( pShellCursor->GetPoint(), pShellCursor->GetPtPos(), - &aTmpState ); - pShellCursor->DeleteMark(); // kde45196-1.html: try to get to a non-hidden paragraph, there must // be one in the document body while (isInHiddenFrame(pShellCursor)) @@ -1872,6 +1867,14 @@ void SwCursorShell::UpdateCursorPos() break; } } + if (isInHiddenFrame(pShellCursor)) + { + SwCursorMoveState aTmpState(CursorMoveState::SetOnlyText); + aTmpState.m_bSetInReadOnly = IsReadOnlyAvailable(); + GetLayout()->GetModelPositionForViewPoint(pShellCursor->GetPoint(), + pShellCursor->GetPtPos(), &aTmpState); + pShellCursor->DeleteMark(); + } } auto* pDoc = GetDoc(); if (pDoc) diff --git a/sw/source/core/text/itrcrsr.cxx b/sw/source/core/text/itrcrsr.cxx index ddb54f8eb0d6..a96433017296 100644 --- a/sw/source/core/text/itrcrsr.cxx +++ b/sw/source/core/text/itrcrsr.cxx @@ -1874,8 +1874,11 @@ TextFrameIndex SwTextCursor::GetModelPositionForViewPoint( SwPosition *pPos, con SwFrame* pLower = pTmp->GetLower(); // Allow non-text-frames to get SwGrfNode for as-char anchored images into pPos // instead of the closest SwTextNode, to be consistent with at-char behavior. - bool bChgNodeInner = pLower - && (pLower->IsTextFrame() || pLower->IsLayoutFrame() || pLower->IsNoTextFrame()); + bool bChgNodeInner + = pLower + && (pLower->IsTextFrame() || pLower->IsLayoutFrame() + || (pLower->IsNoTextFrame() + && (!pCMS || pCMS->m_eState != CursorMoveState::SetOnlyText))); Point aTmpPoint( rPoint ); if ( m_pFrame->IsRightToLeft() )