tdf#137960 tdf#137964 sw: fix Shift-ArrowKey text box movement

A text box and its including shape are now going to keep their
positions in sync along the horizontal (X) axis as well as the
vertical (Y) axis.

Moreover, Shift-UpArrow, Shift-DownArrow, Shift-LeftArrow and
Shift-RightArrow are all going to work the same as the plain
arrow keys, they are just going to move the text a larger
distance.

Change-Id: I49482a101d97927715f47efbf0f58808ea6a8547
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/105328
Tested-by: László Németh <nemeth@numbertext.org>
Reviewed-by: László Németh <nemeth@numbertext.org>
diff --git a/sw/qa/extras/uiwriter/data3/tdf137964.odt b/sw/qa/extras/uiwriter/data3/tdf137964.odt
new file mode 100644
index 0000000..efbb276
--- /dev/null
+++ b/sw/qa/extras/uiwriter/data3/tdf137964.odt
Binary files differ
diff --git a/sw/qa/extras/uiwriter/uiwriter3.cxx b/sw/qa/extras/uiwriter/uiwriter3.cxx
index 477652a..09cad81 100644
--- a/sw/qa/extras/uiwriter/uiwriter3.cxx
+++ b/sw/qa/extras/uiwriter/uiwriter3.cxx
@@ -11,6 +11,8 @@
#include <LibreOfficeKit/LibreOfficeKitEnums.h>
#include <vcl/scheduler.hxx>
#include <com/sun/star/drawing/GraphicExportFilter.hpp>
#include <com/sun/star/drawing/XDrawPageSupplier.hpp>
#include <IDocumentDrawModelAccess.hxx>
#include <com/sun/star/text/TextContentAnchorType.hpp>
#include <com/sun/star/text/XTextTablesSupplier.hpp>
#include <com/sun/star/text/XTextTable.hpp>
@@ -29,6 +31,9 @@
#include <wrtsh.hxx>
#include <unotxdoc.hxx>
#include <docsh.hxx>
#include <drawdoc.hxx>
#include <dcontact.hxx>
#include <svx/svdpage.hxx>

namespace
{
@@ -1905,4 +1910,33 @@ CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf133477)
    CPPUNIT_ASSERT_EQUAL(Color(0, 102, 204), aBitmap.GetPixelColor(0, 0));
}

CPPUNIT_TEST_FIXTURE(SwUiWriterTest3, testTdf137964)
{
    load(DATA_DIRECTORY, "tdf137964.odt");
    SwXTextDocument* pTextDoc = dynamic_cast<SwXTextDocument*>(mxComponent.get());
    CPPUNIT_ASSERT(pTextDoc);

    CPPUNIT_ASSERT_EQUAL(1, getShapes());
    uno::Reference<drawing::XShape> xShape(getShape(1), uno::UNO_QUERY);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(3579), xShape->getPosition().X);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(4090), xShape->getPosition().Y);

    SwDoc* pDoc = pTextDoc->GetDocShell()->GetDoc();
    SwWrtShell* pWrtShell = pDoc->GetDocShell()->GetWrtShell();
    SdrPage* pPage = pDoc->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0);
    SdrObject* pObject = pPage->GetObj(1);
    SwContact* pTextBox = static_cast<SwContact*>(pObject->GetUserCall());
    CPPUNIT_ASSERT_EQUAL(sal_uInt16(RES_FLYFRMFMT), pTextBox->GetFormat()->Which());

    pWrtShell->SelectObj(Point(), 0, pObject);

    pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_SHIFT | KEY_UP);
    pTextDoc->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, KEY_SHIFT | KEY_LEFT);
    Scheduler::ProcessEventsToIdle();

    // Without the fix in place, the shape would have stayed where it was
    CPPUNIT_ASSERT_EQUAL(sal_Int32(2579), xShape->getPosition().X);
    CPPUNIT_ASSERT_EQUAL(sal_Int32(3090), xShape->getPosition().Y);
}

/* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/layout/objectformattertxtfrm.cxx b/sw/source/core/layout/objectformattertxtfrm.cxx
index 6b0e910..e3a9b4e 100644
--- a/sw/source/core/layout/objectformattertxtfrm.cxx
+++ b/sw/source/core/layout/objectformattertxtfrm.cxx
@@ -370,12 +370,25 @@ bool SwObjectFormatterTextFrame::DoFormatObjs()
                                            svl::Items<RES_VERT_ORIENT, RES_ANCHOR>{});

                            const SwRect& rPageFrameArea = pPageFrame->getFrameArea();
                            aSet.Put(SwFormatVertOrient(pObj->GetObjRect().Top() - rPageFrameArea.Top(),
                                                        text::VertOrientation::NONE,
                                                        text::RelOrientation::PAGE_FRAME));
                            aSet.Put(SwFormatAnchor(RndStdIds::FLY_AT_PAGE, pObj->GetPageFrame()->GetPhyPageNum()));
                            if (rFormat.GetVertOrient().GetPos() != pOtherFormat->GetVertOrient().GetPos())
                            {
                                aSet.Put(SwFormatVertOrient(pObj->GetObjRect().Top() - rPageFrameArea.Top(),
                                                            text::VertOrientation::NONE,
                                                            text::RelOrientation::PAGE_FRAME));
                            }
                            if (rFormat.GetHoriOrient().GetPos() != pOtherFormat->GetHoriOrient().GetPos())
                            {
                                aSet.Put(rFormat.GetHoriOrient());
                            }
                            if (rFormat.GetAnchor().GetAnchorId() != pOtherFormat->GetAnchor().GetAnchorId())
                            {
                                aSet.Put(SwFormatAnchor(RndStdIds::FLY_AT_PAGE, pObj->GetPageFrame()->GetPhyPageNum()));
                            }

                            SwTextBoxHelper::syncFlyFrameAttr(rFormat, aSet);
                            if (aSet.Count())
                            {
                                SwTextBoxHelper::syncFlyFrameAttr(rFormat, aSet);
                            }
                        }
                    }
                }
diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx
index 2049e6f..67e0c67 100644
--- a/sw/source/uibase/docvw/edtwin.cxx
+++ b/sw/source/uibase/docvw/edtwin.cxx
@@ -1796,6 +1796,11 @@ KEYINPUT_CHECKTABLE:
                              && rSh.GetDrawView()->AreObjectsMarked() ) )
                    {
                        eKeyState = pFlyFormat ? SwKeyState::Fly_Change : SwKeyState::Draw_Change;
                        if (nSelectionType & SelectionType::DrawObject)
                        {
                            // tdf#137964: always move the DrawObject if one is selected
                            eKeyState = SwKeyState::Draw_Change;
                        }
                        switch ( rKeyCode.GetCode() )
                        {
                            case KEY_RIGHT: nDir = MOVE_RIGHT_HUGE; break;