sw/CppunitTest_sw_core_text.mk  |    1 
 sw/qa/core/text/text.cxx        |   50 ++++++++++++++++++++++++++++++++++++++++
 sw/source/core/text/itrcrsr.cxx |    4 ++-
 3 files changed, 54 insertions(+), 1 deletion(-)

New commits:
commit da9e2b202fb13c6633a813ceb5cc0968799b785d
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Tue Apr 26 15:40:44 2022 +0200
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Wed Apr 27 09:17:00 2022 +0200

    sw: fix double-click opening frame dialog, not graphic dialog on images
    
    The user-visible problem was that once a user clicks on an image a lot
    (e.g. 5 times), then the slot ID dispatched on double-click in
    SwEditWin::MouseButtonDown() is no longer FN_FORMAT_GRAFIC_DLG, but it's
    FN_FORMAT_FRAME_DLG.
    
    This is already inconsistent, but it's especially problematic in case an
    UNO client intercepts only the first UNO command, but not the second
    one.
    
    The other inconsistency is that in practice this only happens for
    as-char images, at-char anchored images work fine.
    
    The reason for this seems to be how we get the doc model position for a
    twips view point. At-char anchored images are handled at
    lcl_GetModelPositionForViewPoint_Objects(), and there we return the
    SwGrfNode in case the view point is inside the frame of the matching fly
    frame. SwTextCursor::GetModelPositionForViewPoint() restricted the same
    to as-char fly frames which have text or layout frame children.
    
    Fix the problem by allowing non-text frame children for as-char images.
    
    (cherry picked from commit 651527b4efe9700c8c8dff58ce5aa86ad5681f16)
    
    Conflicts:
            sw/qa/core/text/text.cxx
    
    Change-Id: If08e7dd2a72f46ebcfb8c6ddf110703eaeb7df6d

diff --git a/sw/CppunitTest_sw_core_text.mk b/sw/CppunitTest_sw_core_text.mk
index cb901fde29f2..f0947a36c65b 100644
--- a/sw/CppunitTest_sw_core_text.mk
+++ b/sw/CppunitTest_sw_core_text.mk
@@ -23,6 +23,7 @@ $(eval $(call gb_CppunitTest_use_libraries,sw_core_text, \
     cppuhelper \
     sal \
     sfx \
+    svl \
     sw \
     test \
     unotest \
diff --git a/sw/qa/core/text/text.cxx b/sw/qa/core/text/text.cxx
index 23f3294b5303..8be07818e7bd 100644
--- a/sw/qa/core/text/text.cxx
+++ b/sw/qa/core/text/text.cxx
@@ -15,6 +15,10 @@
 
 static char const DATA_DIRECTORY[] = "/sw/qa/core/text/data/";
 
+#include <sortedobjs.hxx>
+#include <anchoredobject.hxx>
+#include <fmtcntnt.hxx>
+
 /// Covers sw/source/core/text/ fixes.
 class SwCoreTextTest : public SwModelTestBase
 {
@@ -113,6 +117,52 @@ CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testLineWidth)
     CPPUNIT_ASSERT_GREATER(static_cast<sal_Int32>(65536), nNewLeft - nOldLeft);
 }
 
+CPPUNIT_TEST_FIXTURE(SwCoreTextTest, testAsCharImageDocModelFromViewPoint)
+{
+    // Given a document with an as-char image:
+    loadURL("private:factory/swriter", nullptr);
+    SwXTextDocument* pTextDoc = 
dynamic_cast<SwXTextDocument*>(mxComponent.get());
+    CPPUNIT_ASSERT(pTextDoc);
+    SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
+    uno::Reference<lang::XMultiServiceFactory> xFactory(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<beans::XPropertySet> xTextGraphic(
+        xFactory->createInstance("com.sun.star.text.TextGraphicObject"), 
uno::UNO_QUERY);
+    // Only set the anchor type, the actual bitmap content is not interesting.
+    xTextGraphic->setPropertyValue("AnchorType",
+                                   
uno::makeAny(text::TextContentAnchorType_AS_CHARACTER));
+    uno::Reference<text::XTextDocument> xTextDocument(mxComponent, 
uno::UNO_QUERY);
+    uno::Reference<text::XText> xBodyText = xTextDocument->getText();
+    uno::Reference<text::XTextCursor> xCursor(xBodyText->createTextCursor());
+    uno::Reference<text::XTextContent> xTextContent(xTextGraphic, 
uno::UNO_QUERY);
+    xBodyText->insertTextContent(xCursor, xTextContent, false);
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    SwRootFrame* pRootFrame = pWrtShell->GetLayout();
+    SwFrame* pPageFrame = pRootFrame->GetLower();
+    SwFrame* pBodyFrame = pPageFrame->GetLower();
+    SwFrame* pTextFrame = pBodyFrame->GetLower();
+    const SwSortedObjs& rSortedObjs = *pTextFrame->GetDrawObjs();
+    const SwAnchoredObject* pAnchoredObject = rSortedObjs[0];
+    // The content points to the start node, the next node is the graphic node.
+    SwNodeIndex aGraphicNode = 
*pAnchoredObject->GetFrameFormat().GetContent().GetContentIdx();
+    ++aGraphicNode;
+    tools::Rectangle aFlyFrame = 
pAnchoredObject->GetDrawObj()->GetLastBoundRect();
+    Point aDocPos = aFlyFrame.Center();
+
+    // When translating the view point to the model position:
+    pWrtShell->SttCursorMove();
+    pWrtShell->CallSetCursor(&aDocPos, /*bOnlyText=*/false);
+    pWrtShell->EndCursorMove();
+
+    // Then make sure that we find the graphic node, and not its anchor:
+    SwShellCursor* pShellCursor = pWrtShell->getShellCursor(/*bBlock=*/false);
+    // Without the accompanying fix in place, this test would have failed with:
+    // - Expected: SwNodeIndex (node 6)
+    // - Actual  : SwNodeIndex (node 12)
+    // i.e. the cursor position was the text node hosting the as-char image, 
not the graphic node of
+    // the image.
+    CPPUNIT_ASSERT_EQUAL(aGraphicNode, pShellCursor->GetMark()->nNode);
+}
+
 CPPUNIT_PLUGIN_IMPLEMENT();
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/text/itrcrsr.cxx b/sw/source/core/text/itrcrsr.cxx
index 550dc19054cc..4804eda9dfe0 100644
--- a/sw/source/core/text/itrcrsr.cxx
+++ b/sw/source/core/text/itrcrsr.cxx
@@ -1731,8 +1731,10 @@ TextFrameIndex 
SwTextCursor::GetModelPositionForViewPoint( SwPosition *pPos, con
                 //              (BugId: 9692 + Change in feshview)
                 SwFlyInContentFrame *pTmp = pFlyPor->GetFlyFrame();
                 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->IsTextFrame() || pLower->IsLayoutFrame() || 
pLower->IsNoTextFrame());
                 Point aTmpPoint( rPoint );
 
                 if ( m_pFrame->IsRightToLeft() )

Reply via email to