sw/qa/extras/uiwriter/uiwriter6.cxx |   62 ++++++++++++++++++++++++++++++++++++
 sw/source/core/frmedt/feshview.cxx  |   24 +++++++++++++
 2 files changed, 86 insertions(+)

New commits:
commit 014e5f559a9acf319af24c721dbe6b0bc3bc5882
Author:     László Németh <nem...@numbertext.org>
AuthorDate: Fri May 31 12:38:12 2024 +0200
Commit:     László Németh <nem...@numbertext.org>
CommitDate: Fri May 31 20:46:16 2024 +0200

    tdf#161360 sw: fix cursor position deselecting image in table
    
    In tables, when the selected image was anchored as character
    at beginning of the table row, pressing Escape resulted completely
    lost text cursor (after a short blinking, not visible, missing
    typing etc.) or – in the case of floating tables – cursor in
    a bad position (after the table instead of before the image).
    
    Change-Id: Ib49211ec3531110fc8f5f65fb700318884519666
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168289
    Reviewed-by: László Németh <nem...@numbertext.org>
    Tested-by: Jenkins

diff --git a/sw/qa/extras/uiwriter/uiwriter6.cxx 
b/sw/qa/extras/uiwriter/uiwriter6.cxx
index aedec9304791..a27f506095b3 100644
--- a/sw/qa/extras/uiwriter/uiwriter6.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter6.cxx
@@ -1683,6 +1683,68 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf161332)
     CPPUNIT_ASSERT_EQUAL(SelectionType::Frame, eType2);
 }
 
+CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf161360)
+{
+    createSwDoc("tdf160842.fodt");
+    SwDoc* pDoc = getSwDoc();
+    CPPUNIT_ASSERT(pDoc);
+    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
+    CPPUNIT_ASSERT(pWrtShell);
+    // the cursor is not in the table
+    CPPUNIT_ASSERT(!pWrtShell->IsCursorInTable());
+
+    SwRootFrame* pLayout = pDoc->getIDocumentLayoutAccess().GetCurrentLayout();
+    auto pPage = dynamic_cast<SwPageFrame*>(pLayout->Lower());
+    CPPUNIT_ASSERT(pPage);
+    const SwSortedObjs& rPageObjs = *pPage->GetSortedObjs();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), rPageObjs.size());
+    auto pPageFly = dynamic_cast<SwFlyAtContentFrame*>(rPageObjs[0]);
+    CPPUNIT_ASSERT(pPageFly);
+    auto pTable = dynamic_cast<SwTabFrame*>(pPageFly->GetLower());
+    CPPUNIT_ASSERT(pTable);
+    auto pRow1 = pTable->GetLower();
+    CPPUNIT_ASSERT(pRow1->IsRowFrame());
+    auto pCellA1 = pRow1->GetLower();
+    CPPUNIT_ASSERT(pCellA1);
+    const SwRect& rCellA1Rect = pCellA1->getFrameArea();
+    auto nRowHeight = rCellA1Rect.Height();
+
+    // select image by clicking on it at the center of the upper cell
+    Point ptFrom(rCellA1Rect.Left() + rCellA1Rect.Width() / 2, 
rCellA1Rect.Top() + nRowHeight / 2);
+    vcl::Window& rEditWin = pDoc->GetDocShell()->GetView()->GetEditWin();
+    Point aFrom = rEditWin.LogicToPixel(ptFrom);
+    MouseEvent aClickEvent(aFrom, 1, MouseEventModifiers::SIMPLECLICK, 
MOUSE_LEFT);
+    rEditWin.MouseButtonDown(aClickEvent);
+    rEditWin.MouseButtonUp(aClickEvent);
+
+    // Then make sure that the image is selected:
+    SelectionType eType = pWrtShell->GetSelectionType();
+    CPPUNIT_ASSERT_EQUAL(SelectionType::Graphic, eType);
+
+    // select the text frame instead of the image
+    // by pressing Escape
+    dispatchCommand(mxComponent, ".uno:Escape", {});
+
+    // Then make sure that the cursor in the table:
+    SelectionType eType2 = pWrtShell->GetSelectionType();
+    // This was false (only SelectionType::Text)
+    bool bCursorInTable = eType2 == (SelectionType::Text | 
SelectionType::Table);
+    CPPUNIT_ASSERT(bCursorInTable);
+
+    // select the text frame by pressing Escape again
+    dispatchCommand(mxComponent, ".uno:Escape", {});
+
+    eType2 = pWrtShell->GetSelectionType();
+    CPPUNIT_ASSERT_EQUAL(SelectionType::Frame, eType2);
+
+    // deselect the text frame by pressing Escape again
+    dispatchCommand(mxComponent, ".uno:Escape", {});
+
+    eType2 = pWrtShell->GetSelectionType();
+    // The text cursor is after the floating table
+    CPPUNIT_ASSERT_EQUAL(SelectionType::Text, eType2);
+}
+
 CPPUNIT_TEST_FIXTURE(SwUiWriterTest6, testTdf115132)
 {
     createSwDoc();
diff --git a/sw/source/core/frmedt/feshview.cxx 
b/sw/source/core/frmedt/feshview.cxx
index c10a87110d8e..9a8d7304b4cc 100644
--- a/sw/source/core/frmedt/feshview.cxx
+++ b/sw/source/core/frmedt/feshview.cxx
@@ -191,6 +191,7 @@ bool SwFEShell::SelectObj( const Point& rPt, sal_uInt8 
nFlag, SdrObject *pObj )
                     ( 
pOldSelFly->GetFormat()->GetProtect().IsContentProtected()
                      && !IsReadOnlyAvailable() ))
                 {
+                    SdrObject *pOldObj = 
rMrkList.GetMark(0)->GetMarkedSdrObj();
                     // If a fly is deselected, which contains graphic, OLE or
                     // otherwise, the cursor should be removed from it.
                     // Similar if a fly with protected content is deselected.
@@ -201,6 +202,29 @@ bool SwFEShell::SelectObj( const Point& rPt, sal_uInt8 
nFlag, SdrObject *pObj )
                     bool bUnLockView = !IsViewLocked();
                     LockView( true );
                     SetCursor( aPt, true );
+
+                    // in tables, fix lost position, when the selected image 
was
+                    // anchored as character at beginning of the table row:
+                    // in this case, the text cursor was positionated after the
+                    // floating table, and not before the image, as in other 
positions
+                    // in the table row (and if the table wasn't a floating 
one,
+                    // the text cursor lost completely)
+                    if ( SW_LEAVE_FRAME & nFlag )
+                    {
+                        const SwContact* pContact = GetUserCall(pOldObj);
+                        if ( pContact && pContact->ObjAnchoredAsChar() )
+                        {
+                            const SwNode * pOldNd = 
pContact->GetAnchorNode().FindTableNode();
+                            // the original image was in a table, but the 
cursor is not in that
+                            if ( pOldNd && pOldNd != 
GetCursor()->GetPointNode().FindTableNode() )
+                            {
+                                if ( SwWrtShell* pWrtShell = 
dynamic_cast<SwWrtShell*>(this) )
+                                    // put the text cursor in the same row
+                                    pWrtShell->SelectTableRowCol( aPt );
+                            }
+                        }
+                    }
+
                     if( bUnLockView )
                         LockView( false );
                 }

Reply via email to