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 <nemeth@numbertext.org>
Tested-by: Jenkins
(cherry picked from commit 014e5f559a9acf319af24c721dbe6b0bc3bc5882)
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/168312
Reviewed-by: Michael Stahl <michael.stahl@allotropia.de>
diff --git a/sw/qa/extras/uiwriter/uiwriter6.cxx b/sw/qa/extras/uiwriter/uiwriter6.cxx
index 7ef7a1d..4b994cc 100644
--- a/sw/qa/extras/uiwriter/uiwriter6.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter6.cxx
@@ -1687,6 +1687,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 45229e3..e245743 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 );
}