include/svx/svdedtv.hxx                           |    1 
 include/svx/svdedxv.hxx                           |   13 
 sc/source/ui/inc/drawview.hxx                     |    4 
 sc/source/ui/view/drawview.cxx                    |    9 
 sd/qa/unit/misc-tests.cxx                         |   34 +-
 sd/qa/unit/tiledrendering/data/TextBoxAndRect.odg |binary
 sd/qa/unit/tiledrendering/tiledrendering.cxx      |  339 ++++++++++++++++++++--
 sd/source/ui/inc/View.hxx                         |    3 
 sd/source/ui/view/drviews1.cxx                    |    4 
 sd/source/ui/view/sdview.cxx                      |   10 
 svx/source/svdraw/svddrgmt.cxx                    |    2 
 svx/source/svdraw/svdedtv.cxx                     |   10 
 svx/source/svdraw/svdedtv1.cxx                    |   24 -
 svx/source/svdraw/svdedxv.cxx                     |   17 -
 sw/qa/extras/tiledrendering/data/shape.fodt       |   20 +
 sw/qa/extras/tiledrendering/tiledrendering.cxx    |   16 -
 sw/source/core/draw/dview.cxx                     |   10 
 sw/source/core/inc/dview.hxx                      |    4 
 18 files changed, 456 insertions(+), 64 deletions(-)

New commits:
commit 723db12abd7c238e11dab0271516b6f4415e52eb
Author:     Tomaž Vajngerl <tomaz.vajng...@collabora.co.uk>
AuthorDate: Thu Oct 7 16:48:46 2021 +0200
Commit:     Tomaž Vajngerl <qui...@gmail.com>
CommitDate: Fri Nov 12 14:08:08 2021 +0100

    svx: Don't end text edit mode for all views
    
    This allows multiple views to not disturb each other editing inside
    a impress document. With the ending of text edit for all views still
    enabled, one view can cancel other views text editing just by moving
    or resizing a unrelated shape in the document.
    
    To make this possible we also need a view-local undo manager for
    the text edit mode, which is independent of the document undo
    manager. When the text edit mode ends, all the changes will be
    added as one change to the document undo stack. This prevents any
    conflicts in the undo stack that could be made when 2 views are
    editing the same document at the same time.
    
    This also adds the test for the new use case and changes the existing
    tests to reflect the change.
    
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123220
    Tested-by: Tomaž Vajngerl <qui...@gmail.com>
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>
    (cherry picked from commit c175c1dc19d0edc8ca66e39f0b4b8af04e3d6c87)
    
    Change-Id: I04edb4f91d7e111a490c946f7121cbca75f818d7
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/125070
    Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com>
    Reviewed-by: Tomaž Vajngerl <qui...@gmail.com>

diff --git a/include/svx/svdedtv.hxx b/include/svx/svdedtv.hxx
index 51da6124ed88..71e014970888 100644
--- a/include/svx/svdedtv.hxx
+++ b/include/svx/svdedtv.hxx
@@ -195,6 +195,7 @@ public:
      * Checks if this or other views have an active text edit, if true, end 
them.
      */
     void EndTextEditAllViews() const;
+    void EndTextEditCurrentView();
 
     std::vector< std::unique_ptr<SdrUndoAction> > CreateConnectorUndo( 
SdrObject& rO );
     void AddUndoActions( std::vector< std::unique_ptr<SdrUndoAction> > );
diff --git a/include/svx/svdedxv.hxx b/include/svx/svdedxv.hxx
index 1f9fcf0b898d..737da8ca4896 100644
--- a/include/svx/svdedxv.hxx
+++ b/include/svx/svdedxv.hxx
@@ -104,20 +104,17 @@ protected:
 
 private:
     SfxUndoManager* mpOldTextEditUndoManager;
+    std::unique_ptr<SdrUndoManager> mpLocalTextEditUndoManager;
 
     SVX_DLLPRIVATE void ImpClearVars();
 
 protected:
-    // central method to get an SdrUndoManager for enhanced TextEdit. Default 
will
-    // try to return a dynamic_casted GetModel()->GetSdrUndoManager(). 
Applications
-    // which want to use this feature will need to override this virtual 
method,
-    // provide their document UndoManager and derive it from SdrUndoManager.
-    virtual SdrUndoManager* getSdrUndoManagerForEnhancedTextEdit() const;
+    // Create a local UndoManager that is used for text editing.
+    virtual std::unique_ptr<SdrUndoManager> createLocalTextUndoManager();
 
     void ImpMoveCursorAfterChainingEvent(TextChainCursorManager 
*pCursorManager);
     TextChainCursorManager *ImpHandleMotionThroughBoxesKeyInput(const 
KeyEvent& rKEvt, bool *bOutHandled);
 
-
     OutlinerView* ImpFindOutlinerView(vcl::Window const * pWin) const;
 
     // Create a new OutlinerView at the heap and initialize all required 
parameters.
@@ -177,6 +174,10 @@ public:
     virtual void Notify(SfxBroadcaster& rBC, const SfxHint& rHint) override;
     virtual void ModelHasChanged() override;
 
+    const std::unique_ptr<SdrUndoManager>& getViewLocalUndoManager() const
+    {
+        return mpLocalTextEditUndoManager;
+    }
 
     // TextEdit over an outliner
 
diff --git a/sc/source/ui/inc/drawview.hxx b/sc/source/ui/inc/drawview.hxx
index 46f5598705f2..aa5e1bbb8533 100644
--- a/sc/source/ui/inc/drawview.hxx
+++ b/sc/source/ui/inc/drawview.hxx
@@ -52,8 +52,8 @@ class ScDrawView final : public FmFormView
 
     void ImplClearCalcDropMarker();
 
-    // support enhanced text edit for draw objects
-    virtual SdrUndoManager* getSdrUndoManagerForEnhancedTextEdit() const 
override;
+    // Create a local UndoManager
+    std::unique_ptr<SdrUndoManager> createLocalTextUndoManager() override;
 
 public:
     ScDrawView(
diff --git a/sc/source/ui/view/drawview.cxx b/sc/source/ui/view/drawview.cxx
index c7d12df62209..6959726b4efe 100644
--- a/sc/source/ui/view/drawview.cxx
+++ b/sc/source/ui/view/drawview.cxx
@@ -1103,10 +1103,13 @@ bool ScDrawView::calculateGridOffsetForB2DRange(
     return true;
 }
 
-// support enhanced text edit for draw objects
-SdrUndoManager* ScDrawView::getSdrUndoManagerForEnhancedTextEdit() const
+// Create a new view-local UndoManager manager for Calc
+std::unique_ptr<SdrUndoManager> ScDrawView::createLocalTextUndoManager()
 {
-    return pDoc ? dynamic_cast< SdrUndoManager* >(pDoc->GetUndoManager()) : 
nullptr;
+    std::unique_ptr<SdrUndoManager> pUndoManager(new SdrUndoManager);
+    ScDocShell* pDocShell = pViewData ? pViewData->GetDocShell() : nullptr;
+    pUndoManager->SetDocShell(pDocShell);
+    return pUndoManager;
 }
 
 // #i123922# helper to apply a Graphic to an existing SdrObject
diff --git a/sd/qa/unit/misc-tests.cxx b/sd/qa/unit/misc-tests.cxx
index 5797bdda4348..4e9dfe4c8b59 100644
--- a/sd/qa/unit/misc-tests.cxx
+++ b/sd/qa/unit/misc-tests.cxx
@@ -64,7 +64,7 @@ public:
     void testTdf96206();
     void testTdf96708();
     void testTdf99396();
-    void testTdf99396TextEdit();
+    void testTableObjectUndoTest();
     void testFillGradient();
     void testTdf44774();
     void testTdf38225();
@@ -81,7 +81,7 @@ public:
     CPPUNIT_TEST(testTdf96206);
     CPPUNIT_TEST(testTdf96708);
     CPPUNIT_TEST(testTdf99396);
-    CPPUNIT_TEST(testTdf99396TextEdit);
+    CPPUNIT_TEST(testTableObjectUndoTest);
     CPPUNIT_TEST(testFillGradient);
     CPPUNIT_TEST(testTdf44774);
     CPPUNIT_TEST(testTdf38225);
@@ -252,8 +252,10 @@ void SdMiscTest::testTdf99396()
     xDocSh->DoClose();
 }
 
-void SdMiscTest::testTdf99396TextEdit()
+void SdMiscTest::testTableObjectUndoTest()
 {
+    // See tdf#99396 for the issue
+
     // Load the document and select the table.
     sd::DrawDocShellRef xDocSh = 
Load(m_directories.getURLFromSrc("/sd/qa/unit/data/tdf99396.odp"), ODP);
     sd::ViewShell* pViewShell = xDocSh->GetViewShell();
@@ -279,14 +281,26 @@ void SdMiscTest::testTdf99396TextEdit()
         const SfxItemSet* pArgs = aRequest.GetArgs();
         pView->SetAttributes(*pArgs);
     }
+    const auto& pLocalUndoManager = pView->getViewLocalUndoManager();
+    CPPUNIT_ASSERT_EQUAL(size_t(1), pLocalUndoManager->GetUndoActionCount());
+    CPPUNIT_ASSERT_EQUAL(OUString("Apply attributes"), 
pLocalUndoManager->GetUndoActionComment());
     {
         auto pTableController = 
dynamic_cast<sdr::table::SvxTableController*>(pView->getSelectionController().get());
         CPPUNIT_ASSERT(pTableController);
         SfxRequest aRequest(pViewShell->GetViewFrame(), SID_TABLE_VERT_BOTTOM);
         pTableController->Execute(aRequest);
     }
+    // Global change "Format cell" is applied only - Change the vertical 
alignment to "Bottom"
+    CPPUNIT_ASSERT_EQUAL(size_t(1), 
xDocSh->GetDoc()->GetUndoManager()->GetUndoActionCount());
+    CPPUNIT_ASSERT_EQUAL(OUString("Format cell"), 
xDocSh->GetDoc()->GetUndoManager()->GetUndoActionComment());
+
     pView->SdrEndTextEdit();
 
+    // End of text edit, so the text edit action is added to the undo stack
+    CPPUNIT_ASSERT_EQUAL(size_t(2), 
xDocSh->GetDoc()->GetUndoManager()->GetUndoActionCount());
+    CPPUNIT_ASSERT_EQUAL(OUString("Edit text of Table"), 
xDocSh->GetDoc()->GetUndoManager()->GetUndoActionComment(0));
+    CPPUNIT_ASSERT_EQUAL(OUString("Format cell"), 
xDocSh->GetDoc()->GetUndoManager()->GetUndoActionComment(1));
+
     // Check that the result is what we expect.
     {
         uno::Reference<table::XTable> xTable = pTableObject->getTable();
@@ -304,6 +318,10 @@ void SdMiscTest::testTdf99396TextEdit()
     // Now undo.
     xDocSh->GetUndoManager()->Undo();
 
+    // Undoing the last action - one left
+    CPPUNIT_ASSERT_EQUAL(size_t(1), 
xDocSh->GetDoc()->GetUndoManager()->GetUndoActionCount());
+    CPPUNIT_ASSERT_EQUAL(OUString("Format cell"), 
xDocSh->GetDoc()->GetUndoManager()->GetUndoActionComment(0));
+
     // Check again that the result is what we expect.
     {
         uno::Reference<table::XTable> xTable = pTableObject->getTable();
@@ -319,6 +337,9 @@ void SdMiscTest::testTdf99396TextEdit()
         CPPUNIT_ASSERT_EQUAL(SvxAdjust::Center, pAdjust->GetAdjust());
     }
 
+    Scheduler::ProcessEventsToIdle();
+    CPPUNIT_ASSERT_EQUAL(size_t(1), 
xDocSh->GetDoc()->GetUndoManager()->GetUndoActionCount());
+    CPPUNIT_ASSERT_EQUAL(OUString("Format cell"), 
xDocSh->GetDoc()->GetUndoManager()->GetUndoActionComment(0));
 
     /*
      * now test tdf#103950 - Undo does not revert bundled font size changes 
for table cells
@@ -329,8 +350,11 @@ void SdMiscTest::testTdf99396TextEdit()
         SfxRequest aRequest(pViewShell->GetViewFrame(), SID_GROW_FONT_SIZE);
         static_cast<sd::DrawViewShell*>(pViewShell)->ExecChar(aRequest);
     }
-    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), 
xDocSh->GetDoc()->GetUndoManager()->GetUndoActionCount());
-
+    Scheduler::ProcessEventsToIdle();
+    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(3), 
xDocSh->GetDoc()->GetUndoManager()->GetUndoActionCount());
+    CPPUNIT_ASSERT_EQUAL(OUString("Apply attributes to Table"), 
xDocSh->GetDoc()->GetUndoManager()->GetUndoActionComment(0));
+    CPPUNIT_ASSERT_EQUAL(OUString("Grow font size"), 
xDocSh->GetDoc()->GetUndoManager()->GetUndoActionComment(1));
+    CPPUNIT_ASSERT_EQUAL(OUString("Format cell"), 
xDocSh->GetDoc()->GetUndoManager()->GetUndoActionComment(2));
 
     xDocSh->DoClose();
 }
diff --git a/sd/qa/unit/tiledrendering/data/TextBoxAndRect.odg 
b/sd/qa/unit/tiledrendering/data/TextBoxAndRect.odg
new file mode 100644
index 000000000000..aa1a37b83147
Binary files /dev/null and b/sd/qa/unit/tiledrendering/data/TextBoxAndRect.odg 
differ
diff --git a/sd/qa/unit/tiledrendering/tiledrendering.cxx 
b/sd/qa/unit/tiledrendering/tiledrendering.cxx
index 99c30b852a40..fae683532057 100644
--- a/sd/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx
@@ -132,6 +132,7 @@ public:
     void testSlideDuplicateUndo();
     void testMoveShapeHandle();
     void testDeleteTable();
+    void testShapeEditInMultipleViews();
 
     CPPUNIT_TEST_SUITE(SdTiledRenderingTest);
     CPPUNIT_TEST(testCreateDestroy);
@@ -189,7 +190,7 @@ public:
     CPPUNIT_TEST(testSlideDuplicateUndo);
     CPPUNIT_TEST(testMoveShapeHandle);
     CPPUNIT_TEST(testDeleteTable);
-
+    CPPUNIT_TEST(testShapeEditInMultipleViews);
     CPPUNIT_TEST_SUITE_END();
 
 private:
@@ -1316,6 +1317,38 @@ void SdTiledRenderingTest::testUndoLimiting()
     Scheduler::ProcessEventsToIdle();
     CPPUNIT_ASSERT(pViewShell1->GetView()->IsTextEdit());
 
+    // View2 UNDO stack should be empty
+    {
+        SfxRequest aReq2(SID_UNDO, SfxCallMode::SLOT, 
pXImpressDocument->GetDocShell()->GetDoc()->GetPool());
+        aReq2.AppendItem(SfxUInt16Item(SID_UNDO, 1));
+        pViewShell2->ExecuteSlot(aReq2);
+        const auto* pReturnValue = aReq2.GetReturnValue();
+        CPPUNIT_ASSERT(!pReturnValue);
+    }
+
+    // View1 can UNDO
+    {
+        SfxRequest aReq1(SID_UNDO, SfxCallMode::SLOT, 
pXImpressDocument->GetDocShell()->GetDoc()->GetPool());
+        aReq1.AppendItem(SfxUInt16Item(SID_UNDO, 1));
+        pViewShell1->ExecuteSlot(aReq1);
+        CPPUNIT_ASSERT(aReq1.IsDone());
+    }
+
+    // View1 can REDO
+    {
+        SfxRequest aReq1(SID_REDO, SfxCallMode::SLOT, 
pXImpressDocument->GetDocShell()->GetDoc()->GetPool());
+        aReq1.AppendItem(SfxUInt16Item(SID_REDO, 1));
+        pViewShell1->ExecuteSlot(aReq1);
+        CPPUNIT_ASSERT(aReq1.IsDone());
+    }
+
+    // Exit text edit mode
+    pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, 
awt::Key::ESCAPE);
+    pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE);
+    Scheduler::ProcessEventsToIdle();
+
+    CPPUNIT_ASSERT(!pViewShell1->GetView()->IsTextEdit());
+
     // Now check view2 cannot undo actions.
     {
         SfxRequest aReq2(SID_UNDO, SfxCallMode::SLOT, 
pXImpressDocument->GetDocShell()->GetDoc()->GetPool());
@@ -2073,11 +2106,19 @@ void SdTiledRenderingTest::testDisableUndoRepair()
 {
     // Load the document.
     SdXImpressDocument* pXImpressDocument = createDoc("dummy.odp");
+
+    // Create View 1
     SfxViewShell* pView1 = SfxViewShell::Current();
+    sd::ViewShell* pViewShell1 = 
pXImpressDocument->GetDocShell()->GetViewShell();
     int nView1 = SfxLokHelper::getView();
+
+    // Create View 2
     SfxLokHelper::createView();
     SfxViewShell* pView2 = SfxViewShell::Current();
+    sd::ViewShell* pViewShell2 = 
pXImpressDocument->GetDocShell()->GetViewShell();
     int nView2 = SfxLokHelper::getView();
+
+    // Check UNDO is disabled
     {
         std::unique_ptr<SfxPoolItem> pItem1;
         std::unique_ptr<SfxPoolItem> pItem2;
@@ -2092,15 +2133,24 @@ void SdTiledRenderingTest::testDisableUndoRepair()
     pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'h', 0);
     pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'h', 0);
     Scheduler::ProcessEventsToIdle();
+    CPPUNIT_ASSERT(pViewShell1->GetView()->IsTextEdit());
+    pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, 
awt::Key::ESCAPE);
+    pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE);
+    Scheduler::ProcessEventsToIdle();
+    CPPUNIT_ASSERT(!pViewShell1->GetView()->IsTextEdit());
+
+    // Check
     {
         std::unique_ptr<SfxPoolItem> xItem1;
-        std::unique_ptr<SfxPoolItem> xItem2;
         pView1->GetViewFrame()->GetBindings().QueryState(SID_UNDO, xItem1);
+        const auto* pUInt32Item1 = dynamic_cast<const 
SfxUInt32Item*>(xItem1.get());
+        CPPUNIT_ASSERT(!pUInt32Item1);
+
+        std::unique_ptr<SfxPoolItem> xItem2;
         pView2->GetViewFrame()->GetBindings().QueryState(SID_UNDO, xItem2);
-        CPPUNIT_ASSERT(!dynamic_cast< const SfxUInt32Item* >(xItem1.get()));
-        const SfxUInt32Item* pUInt32Item = dynamic_cast<const 
SfxUInt32Item*>(xItem2.get());
-        CPPUNIT_ASSERT(pUInt32Item);
-        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(SID_REPAIRPACKAGE), 
pUInt32Item->GetValue());
+        const auto* pUInt32Item2 = dynamic_cast<const 
SfxUInt32Item*>(xItem2.get());
+        CPPUNIT_ASSERT(pUInt32Item2);
+        CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(SID_REPAIRPACKAGE), 
pUInt32Item2->GetValue());
     }
 
     // Insert a character in the second view.
@@ -2111,15 +2161,23 @@ void SdTiledRenderingTest::testDisableUndoRepair()
     pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'c', 0);
     pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'c', 0);
     Scheduler::ProcessEventsToIdle();
+    CPPUNIT_ASSERT(pViewShell2->GetView()->IsTextEdit());
+    pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, 
awt::Key::ESCAPE);
+    pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE);
+    Scheduler::ProcessEventsToIdle();
+    CPPUNIT_ASSERT(!pViewShell2->GetView()->IsTextEdit());
+
+    // Check
     {
         std::unique_ptr<SfxPoolItem> xItem1;
-        std::unique_ptr<SfxPoolItem> xItem2;
         pView1->GetViewFrame()->GetBindings().QueryState(SID_UNDO, xItem1);
-        pView2->GetViewFrame()->GetBindings().QueryState(SID_UNDO, xItem2);
-        CPPUNIT_ASSERT(!dynamic_cast< const SfxUInt32Item* >(xItem2.get()));
         const SfxUInt32Item* pUInt32Item = dynamic_cast<const 
SfxUInt32Item*>(xItem1.get());
         CPPUNIT_ASSERT(pUInt32Item);
         CPPUNIT_ASSERT_EQUAL(static_cast<sal_uInt32>(SID_REPAIRPACKAGE), 
pUInt32Item->GetValue());
+
+        std::unique_ptr<SfxPoolItem> xItem2;
+        pView2->GetViewFrame()->GetBindings().QueryState(SID_UNDO, xItem2);
+        CPPUNIT_ASSERT(!dynamic_cast< const SfxUInt32Item* >(xItem2.get()));
     }
 }
 
@@ -2136,17 +2194,20 @@ void SdTiledRenderingTest::testDocumentRepair()
     SfxLokHelper::createView();
     SfxViewShell* pView2 = SfxViewShell::Current();
     int nView2 = SfxLokHelper::getView();
+    sd::ViewShell* pViewShell2 = 
pXImpressDocument->GetDocShell()->GetViewShell();
+
     CPPUNIT_ASSERT(pView1 != pView2);
     {
         std::unique_ptr<SfxPoolItem> xItem1;
-        std::unique_ptr<SfxPoolItem> xItem2;
         pView1->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, 
xItem1);
-        pView2->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, 
xItem2);
         const SfxBoolItem* pItem1 = dynamic_cast<const 
SfxBoolItem*>(xItem1.get());
-        const SfxBoolItem* pItem2 = dynamic_cast<const 
SfxBoolItem*>(xItem2.get());
         CPPUNIT_ASSERT(pItem1);
-        CPPUNIT_ASSERT(pItem2);
         CPPUNIT_ASSERT_EQUAL(false, pItem1->GetValue());
+
+        std::unique_ptr<SfxPoolItem> xItem2;
+        pView2->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, 
xItem2);
+        const SfxBoolItem* pItem2 = dynamic_cast<const 
SfxBoolItem*>(xItem2.get());
+        CPPUNIT_ASSERT(pItem2);
         CPPUNIT_ASSERT_EQUAL(false, pItem2->GetValue());
     }
 
@@ -2158,16 +2219,23 @@ void SdTiledRenderingTest::testDocumentRepair()
     pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'c', 0);
     pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'c', 0);
     Scheduler::ProcessEventsToIdle();
+    CPPUNIT_ASSERT(pViewShell2->GetView()->IsTextEdit());
+    pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, 
awt::Key::ESCAPE);
+    pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::ESCAPE);
+    Scheduler::ProcessEventsToIdle();
+    CPPUNIT_ASSERT(!pViewShell2->GetView()->IsTextEdit());
+
     {
         std::unique_ptr<SfxPoolItem> xItem1;
-        std::unique_ptr<SfxPoolItem> xItem2;
         pView1->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, 
xItem1);
-        pView2->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, 
xItem2);
         const SfxBoolItem* pItem1 = dynamic_cast<const 
SfxBoolItem*>(xItem1.get());
-        const SfxBoolItem* pItem2 = dynamic_cast<const 
SfxBoolItem*>(xItem2.get());
         CPPUNIT_ASSERT(pItem1);
-        CPPUNIT_ASSERT(pItem2);
         CPPUNIT_ASSERT_EQUAL(true, pItem1->GetValue());
+
+        std::unique_ptr<SfxPoolItem> xItem2;
+        pView2->GetViewFrame()->GetBindings().QueryState(SID_DOC_REPAIR, 
xItem2);
+        const SfxBoolItem* pItem2 = dynamic_cast<const 
SfxBoolItem*>(xItem2.get());
+        CPPUNIT_ASSERT(pItem2);
         CPPUNIT_ASSERT_EQUAL(true, pItem2->GetValue());
     }
 }
@@ -2689,7 +2757,244 @@ void SdTiledRenderingTest::testMoveShapeHandle()
         CPPUNIT_ASSERT_EQUAL(x-1, oldX);
         CPPUNIT_ASSERT_EQUAL(y-1, oldY);
     }
+}
+
+void SdTiledRenderingTest::testShapeEditInMultipleViews()
+{
+    SdXImpressDocument* pXImpressDocument = createDoc("TextBoxAndRect.odg");
+    
pXImpressDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>());
+    SdDrawDocument* pDocument = pXImpressDocument->GetDoc();
+
+    // Create view 1
+    const int nView1 = SfxLokHelper::getView();
+    sd::ViewShell* pViewShell1 = 
pXImpressDocument->GetDocShell()->GetViewShell();
+    SdrView* pView1 = pViewShell1->GetView();
+    Scheduler::ProcessEventsToIdle();
+
+    // Create view 2
+    SfxLokHelper::createView();
+    const int nView2 = SfxLokHelper::getView();
+    CPPUNIT_ASSERT(nView1 != nView2);
+
+    sd::ViewShell* pViewShell2 = 
pXImpressDocument->GetDocShell()->GetViewShell();
+    SdrView* pView2 = pViewShell2->GetView();
+    Scheduler::ProcessEventsToIdle();
+
+    // Switch to view 1
+    SfxLokHelper::setView(nView1);
+
+    SdPage* pPage1 = pViewShell1->GetActualPage();
+
+    SdrObject* pTextBoxObject = pPage1->GetObj(0);
+    CPPUNIT_ASSERT_EQUAL(OUString("Text Box"), pTextBoxObject->GetName());
+
+    SdrObject* pRectangleObject = pPage1->GetObj(1);
+    CPPUNIT_ASSERT_EQUAL(OUString("Rect"), pRectangleObject->GetName());
+
+    SdrObject* pTableObject = pPage1->GetObj(2);
+    CPPUNIT_ASSERT_EQUAL(OUString("Table1"), pTableObject->GetName());
+
+    // Scenario 1
+    // 2 shapes - "Text Box" and "Rect"
+    // View1 - "Text Box" enters text edit mode, View 2 - moves the "Rect" 
around
+    {
+        sd::UndoManager* pUndoManager = pDocument->GetUndoManager();
+        CPPUNIT_ASSERT_EQUAL(size_t(0), pUndoManager->GetUndoActionCount());
+
+        pView1->SdrBeginTextEdit(pTextBoxObject);
+        CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit());
+        CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+
+        // Local undo count for View1 is 0
+        CPPUNIT_ASSERT_EQUAL(size_t(0), 
pView1->getViewLocalUndoManager()->GetUndoActionCount());
+        // Write 'test' in View1
+        SfxStringItem aInputString(SID_ATTR_CHAR, "test");
+        
pViewShell1->GetViewFrame()->GetDispatcher()->ExecuteList(SID_ATTR_CHAR, 
SfxCallMode::SYNCHRON, { &aInputString });
+        // Local undo count for View1 is now 1
+        CPPUNIT_ASSERT_EQUAL(size_t(1), 
pView1->getViewLocalUndoManager()->GetUndoActionCount());
+
+        // Mark rectangle object
+        pView2->MarkObj(pRectangleObject, pView2->GetSdrPageView());
+
+        // Check the initial position of the object
+        tools::Rectangle aRectangle = pRectangleObject->GetLogicRect();
+        CPPUNIT_ASSERT_EQUAL(6250L, aRectangle.TopLeft().X());
+        CPPUNIT_ASSERT_EQUAL(7000L, aRectangle.TopLeft().Y());
+        CPPUNIT_ASSERT_EQUAL(6501L, aRectangle.GetWidth());
+        CPPUNIT_ASSERT_EQUAL(4501L, aRectangle.GetHeight());
+
+        // On View2 - Move handle 0 on the shape to a new mosition - resize
+        Point aNewPosition = aRectangle.TopLeft() + Point(-1250, -1000);
+        pView2->MoveShapeHandle(0, aNewPosition, -1);
+        Scheduler::ProcessEventsToIdle();
+        CPPUNIT_ASSERT_EQUAL(size_t(1), pUndoManager->GetUndoActionCount());
+
+        // Check the object has a new size
+        aRectangle = pRectangleObject->GetLogicRect();
+        CPPUNIT_ASSERT_EQUAL(5000L, aRectangle.TopLeft().X());
+        CPPUNIT_ASSERT_EQUAL(6000L, aRectangle.TopLeft().Y());
+        CPPUNIT_ASSERT_EQUAL(7751L, aRectangle.GetWidth());
+        CPPUNIT_ASSERT_EQUAL(5501L, aRectangle.GetHeight());
+
+        // View1 is still in text edit mode...
+        CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit());
+        CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+
+        // On View2 - relative move the shape to a different position
+        pView2->MoveMarkedObj(Size(1000, 2000), /*bCopy=*/false);
+        Scheduler::ProcessEventsToIdle();
+        CPPUNIT_ASSERT_EQUAL(size_t(2), pUndoManager->GetUndoActionCount());
+
+        // Check the object is at a different position
+        aRectangle = pRectangleObject->GetLogicRect();
+        CPPUNIT_ASSERT_EQUAL(6000L, aRectangle.TopLeft().X());
+        CPPUNIT_ASSERT_EQUAL(8000L, aRectangle.TopLeft().Y());
+        CPPUNIT_ASSERT_EQUAL(7751L, aRectangle.GetWidth());
+        CPPUNIT_ASSERT_EQUAL(5501L, aRectangle.GetHeight());
+
+        // View1 is still in text edit mode...
+        CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit());
+        CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+
+        // End Text edit - check undo count increase from 2 -> 3
+        CPPUNIT_ASSERT_EQUAL(size_t(2), pUndoManager->GetUndoActionCount());
+        pView1->SdrEndTextEdit();
+        Scheduler::ProcessEventsToIdle();
+        CPPUNIT_ASSERT_EQUAL(size_t(3), pUndoManager->GetUndoActionCount());
+
+        // Check that both views exited the text edit mode
+        CPPUNIT_ASSERT_EQUAL(false, pView1->IsTextEdit());
+        CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+    }
 
+    // Scenario 2
+    // 1 shapes - "Text Box"
+    // View1 - "Text Box" enters text edit mode, View 2 - moves the "Text Box" 
around
+    {
+        sd::UndoManager* pUndoManager = pDocument->GetUndoManager();
+        CPPUNIT_ASSERT_EQUAL(size_t(3), pUndoManager->GetUndoActionCount());
+
+        pView1->SdrBeginTextEdit(pTextBoxObject);
+        CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit());
+        CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+
+        // Local undo count for View1 is 0
+        CPPUNIT_ASSERT_EQUAL(size_t(0), 
pView1->getViewLocalUndoManager()->GetUndoActionCount());
+        // Write 'test' in View1
+        SfxStringItem aInputString(SID_ATTR_CHAR, "test");
+        
pViewShell1->GetViewFrame()->GetDispatcher()->ExecuteList(SID_ATTR_CHAR, 
SfxCallMode::SYNCHRON, { &aInputString });
+        // Local undo count for View1 is now 1
+        CPPUNIT_ASSERT_EQUAL(size_t(1), 
pView1->getViewLocalUndoManager()->GetUndoActionCount());
+
+        // Mark rectangle object
+        pView2->MarkObj(pTextBoxObject, pView2->GetSdrPageView());
+
+        // Check the initial position of the object
+        tools::Rectangle aRectangle = pTextBoxObject->GetLogicRect();
+        CPPUNIT_ASSERT_EQUAL(2250L, aRectangle.TopLeft().X());
+        CPPUNIT_ASSERT_EQUAL(2000L, aRectangle.TopLeft().Y());
+        CPPUNIT_ASSERT_EQUAL(4501L, aRectangle.GetWidth());
+        CPPUNIT_ASSERT_EQUAL(2001L, aRectangle.GetHeight());
+
+        // On View2 - Move handle 0 on the shape to a new mosition - resize
+        Point aNewPosition = aRectangle.TopLeft() + Point(-1250, -1000);
+        pView2->MoveShapeHandle(0, aNewPosition, -1);
+        Scheduler::ProcessEventsToIdle();
+        CPPUNIT_ASSERT_EQUAL(size_t(4), pUndoManager->GetUndoActionCount());
+
+        // Check the object has a new size
+        aRectangle = pTextBoxObject->GetLogicRect();
+        CPPUNIT_ASSERT_EQUAL(1000L, aRectangle.TopLeft().X());
+        CPPUNIT_ASSERT_EQUAL(1000L, aRectangle.TopLeft().Y());
+        CPPUNIT_ASSERT_EQUAL(4990L, aRectangle.GetWidth());
+        CPPUNIT_ASSERT_EQUAL(2175L, aRectangle.GetHeight());
+
+        // View1 is still in text edit mode...
+        CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit());
+        CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+
+        // On View2 - relative move the shape to a different position
+        pView2->MoveMarkedObj(Size(1000, 2000), /*bCopy=*/false);
+        Scheduler::ProcessEventsToIdle();
+        CPPUNIT_ASSERT_EQUAL(size_t(5), pUndoManager->GetUndoActionCount());
+
+        // Check the object is at a different position
+        aRectangle = pTextBoxObject->GetLogicRect();
+        CPPUNIT_ASSERT_EQUAL(2000L, aRectangle.TopLeft().X());
+        CPPUNIT_ASSERT_EQUAL(3000L, aRectangle.TopLeft().Y());
+        CPPUNIT_ASSERT_EQUAL(4990L, aRectangle.GetWidth());
+        CPPUNIT_ASSERT_EQUAL(2175L, aRectangle.GetHeight());
+
+        // View1 is still in text edit mode...
+        CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit());
+        CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+
+        // End Text edit - check undo count increase from 5 -> 6
+        CPPUNIT_ASSERT_EQUAL(size_t(5), pUndoManager->GetUndoActionCount());
+        pView1->SdrEndTextEdit();
+        Scheduler::ProcessEventsToIdle();
+        CPPUNIT_ASSERT_EQUAL(size_t(6), pUndoManager->GetUndoActionCount());
+
+        // Check that both views exited the text edit mode
+        CPPUNIT_ASSERT_EQUAL(false, pView1->IsTextEdit());
+        CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+    }
+
+    // Scenario 3
+    // 1 shapes - "Table1"
+    // View1 - "Table1" enters text edit mode, View 2 - moves the "Table1" 
around
+    {
+        sd::UndoManager* pUndoManager = pDocument->GetUndoManager();
+        CPPUNIT_ASSERT_EQUAL(size_t(6), pUndoManager->GetUndoActionCount());
+
+        pView1->SdrBeginTextEdit(pTableObject);
+        CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit());
+        CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+
+        // Local undo count for View1 is 0
+        CPPUNIT_ASSERT_EQUAL(size_t(0), 
pView1->getViewLocalUndoManager()->GetUndoActionCount());
+        // Write 'test' in View1
+        SfxStringItem aInputString(SID_ATTR_CHAR, "test");
+        
pViewShell1->GetViewFrame()->GetDispatcher()->ExecuteList(SID_ATTR_CHAR, 
SfxCallMode::SYNCHRON, { &aInputString });
+        // Local undo count for View1 is now 1
+        CPPUNIT_ASSERT_EQUAL(size_t(1), 
pView1->getViewLocalUndoManager()->GetUndoActionCount());
+
+        // Mark rectangle object
+        pView2->MarkObj(pTableObject, pView2->GetSdrPageView());
+
+        // Check the initial position of the table
+        tools::Rectangle aRectangle = pTableObject->GetLogicRect();
+        CPPUNIT_ASSERT_EQUAL(2919L, aRectangle.TopLeft().X());
+        CPPUNIT_ASSERT_EQUAL(18063L, aRectangle.TopLeft().Y());
+        CPPUNIT_ASSERT_EQUAL(14099L, aRectangle.GetWidth());
+        CPPUNIT_ASSERT_EQUAL(5999L, aRectangle.GetHeight());
+
+        // On View2 - relative move the shape to a different position
+        pView2->MoveMarkedObj(Size(1000, 2000), /*bCopy=*/false);
+        Scheduler::ProcessEventsToIdle();
+        CPPUNIT_ASSERT_EQUAL(size_t(7), pUndoManager->GetUndoActionCount());
+
+        // Check the object is at a different position
+        aRectangle = pTableObject->GetLogicRect();
+        CPPUNIT_ASSERT_EQUAL(3919L, aRectangle.TopLeft().X());
+        CPPUNIT_ASSERT_EQUAL(20063L, aRectangle.TopLeft().Y());
+        CPPUNIT_ASSERT_EQUAL(14099L, aRectangle.GetWidth());
+        CPPUNIT_ASSERT_EQUAL(5999L, aRectangle.GetHeight());
+
+        // View1 is still in text edit mode...
+        CPPUNIT_ASSERT_EQUAL(true, pView1->IsTextEdit());
+        CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+
+        // End Text edit - check undo count increase from 7 -> 8
+        CPPUNIT_ASSERT_EQUAL(size_t(7), pUndoManager->GetUndoActionCount());
+        pView1->SdrEndTextEdit();
+        Scheduler::ProcessEventsToIdle();
+        CPPUNIT_ASSERT_EQUAL(size_t(8), pUndoManager->GetUndoActionCount());
+
+        // Check that both views exited the text edit mode
+        CPPUNIT_ASSERT_EQUAL(false, pView1->IsTextEdit());
+        CPPUNIT_ASSERT_EQUAL(false, pView2->IsTextEdit());
+    }
 }
 CPPUNIT_TEST_SUITE_REGISTRATION(SdTiledRenderingTest);
 
diff --git a/sd/source/ui/inc/View.hxx b/sd/source/ui/inc/View.hxx
index 4693ce3e9596..152ed5d33c91 100644
--- a/sd/source/ui/inc/View.hxx
+++ b/sd/source/ui/inc/View.hxx
@@ -139,6 +139,9 @@ public:
     ViewShell* GetViewShell() const { return mpViewSh; }
     SfxViewShell* GetSfxViewShell() const override;
 
+    // Create a local UndoManager
+    std::unique_ptr<SdrUndoManager> createLocalTextUndoManager() override;
+
     virtual bool SdrBeginTextEdit(SdrObject* pObj, SdrPageView* pPV = nullptr, 
vcl::Window* pWin = nullptr, bool bIsNewObj = false,
         SdrOutliner* pGivenOutliner = nullptr, OutlinerView* 
pGivenOutlinerView = nullptr,
         bool bDontDeleteOutliner = false, bool bOnlyOneView = false, bool 
bGrabFocus = true) override;
diff --git a/sd/source/ui/view/drviews1.cxx b/sd/source/ui/view/drviews1.cxx
index bdbf06b72361..468a2cba3078 100644
--- a/sd/source/ui/view/drviews1.cxx
+++ b/sd/source/ui/view/drviews1.cxx
@@ -343,7 +343,9 @@ void DrawViewShell::ChangeEditMode(EditMode eEMode, bool 
bIsLayerModeActive)
 
     if ( mpDrawView->IsTextEdit() )
     {
-        mpDrawView->SdrEndTextEdit();
+        // This exits the text edit mode when going in and out of window 
focus, which is not needed
+        // Let's keep this call as comment for now as it probably just needs a 
better conditional.
+        // mpDrawView->SdrEndTextEdit();
     }
 
     LayerTabBar* pLayerBar = GetLayerTabControl();
diff --git a/sd/source/ui/view/sdview.cxx b/sd/source/ui/view/sdview.cxx
index 0abaff31fc9f..f6bf3381231b 100644
--- a/sd/source/ui/view/sdview.cxx
+++ b/sd/source/ui/view/sdview.cxx
@@ -79,6 +79,8 @@
 #include <LibreOfficeKit/LibreOfficeKitEnums.h>
 #include <DrawController.hxx>
 
+#include <undo/undomanager.hxx>
+
 #include <memory>
 #include <numeric>
 
@@ -618,6 +620,14 @@ SfxViewShell* View::GetSfxViewShell() const
     return pRet;
 }
 
+// Create a new view-local UndoManager manager for Impress/Draw
+std::unique_ptr<SdrUndoManager> View::createLocalTextUndoManager()
+{
+    std::unique_ptr<SdrUndoManager> pUndoManager(new sd::UndoManager);
+    pUndoManager->SetDocShell(mpDocSh);
+    return pUndoManager;
+}
+
 bool View::SdrBeginTextEdit(
     SdrObject* pObj, SdrPageView* pPV, vcl::Window* pWin,
     bool bIsNewObj,
diff --git a/svx/source/svdraw/svddrgmt.cxx b/svx/source/svdraw/svddrgmt.cxx
index 80c421e40149..bbb640e6c6c7 100644
--- a/svx/source/svdraw/svddrgmt.cxx
+++ b/svx/source/svdraw/svddrgmt.cxx
@@ -1360,7 +1360,7 @@ bool SdrDragObjOwn::EndSdrDrag(bool /*bCopy*/)
 
         if( bUndo )
         {
-            getSdrDragView().EndTextEditAllViews();
+            getSdrDragView().EndTextEditCurrentView();
             if(!getSdrDragView().IsInsObjPoint() && pObj->IsInserted() )
             {
                 if (DragStat().IsEndDragChangesAttributes())
diff --git a/svx/source/svdraw/svdedtv.cxx b/svx/source/svdraw/svdedtv.cxx
index b48174ad8b57..44d9684e2ef9 100644
--- a/svx/source/svdraw/svdedtv.cxx
+++ b/svx/source/svdraw/svdedtv.cxx
@@ -1059,4 +1059,14 @@ void SdrEditView::EndTextEditAllViews() const
     }
 }
 
+void SdrEditView::EndTextEditCurrentView()
+{
+    if (IsTextEdit())
+    {
+        SdrView* pSdrView = dynamic_cast<SdrView*>(this);
+        if (pSdrView)
+            pSdrView->SdrEndTextEdit();
+    }
+}
+
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/svx/source/svdraw/svdedtv1.cxx b/svx/source/svdraw/svdedtv1.cxx
index 830ef238c590..21a0830bbd1a 100644
--- a/svx/source/svdraw/svdedtv1.cxx
+++ b/svx/source/svdraw/svdedtv1.cxx
@@ -99,7 +99,7 @@ void SdrEditView::SetMarkedObjRect(const tools::Rectangle& 
rRect)
     const bool bUndo = IsUndoEnabled();
     if( bUndo )
     {
-        EndTextEditAllViews();
+        EndTextEditCurrentView();
         BegUndo(ImpGetDescriptionString(STR_EditPosSize));
     }
 
@@ -190,7 +190,7 @@ void SdrEditView::MoveMarkedObj(const Size& rSiz, bool 
bCopy)
 
     if( bUndo )
     {
-        EndTextEditAllViews();
+        EndTextEditCurrentView();
         OUString aStr(SvxResId(STR_EditMove));
         if (bCopy)
             aStr += SvxResId(STR_EditWithCopy);
@@ -223,7 +223,7 @@ void SdrEditView::ResizeMarkedObj(const Point& rRef, const 
Fraction& xFact, cons
     const bool bUndo = IsUndoEnabled();
     if( bUndo )
     {
-        EndTextEditAllViews();
+        EndTextEditCurrentView();
         OUString aStr {ImpGetDescriptionString(STR_EditResize)};
         if (bCopy)
             aStr+=SvxResId(STR_EditWithCopy);
@@ -258,7 +258,7 @@ void SdrEditView::ResizeMultMarkedObj(const Point& rRef,
     const bool bUndo = IsUndoEnabled();
     if( bUndo )
     {
-        EndTextEditAllViews();
+        EndTextEditCurrentView();
         BegUndo(ImpGetDescriptionString(STR_EditResize));
     }
 
@@ -319,7 +319,7 @@ void SdrEditView::RotateMarkedObj(const Point& rRef, long 
nAngle, bool bCopy)
     const bool bUndo = IsUndoEnabled();
     if( bUndo )
     {
-        EndTextEditAllViews();
+        EndTextEditCurrentView();
         OUString aStr {ImpGetDescriptionString(STR_EditRotate)};
         if (bCopy) aStr+=SvxResId(STR_EditWithCopy);
         BegUndo(aStr);
@@ -376,7 +376,7 @@ void SdrEditView::MirrorMarkedObj(const Point& rRef1, const 
Point& rRef2, bool b
 
     if( bUndo )
     {
-        EndTextEditAllViews();
+        EndTextEditCurrentView();
         OUString aStr;
         Point aDif(rRef2-rRef1);
         if (aDif.X()==0)
@@ -476,7 +476,7 @@ void SdrEditView::ShearMarkedObj(const Point& rRef, long 
nAngle, bool bVShear, b
 
     if( bUndo )
     {
-        EndTextEditAllViews();
+        EndTextEditCurrentView();
         OUString aStr {ImpGetDescriptionString(STR_EditShear)};
         if (bCopy)
             aStr+=SvxResId(STR_EditWithCopy);
@@ -592,7 +592,7 @@ void SdrEditView::CrookMarkedObj(const Point& rRef, const 
Point& rRad, SdrCrookM
 
     if( bUndo )
     {
-        EndTextEditAllViews();
+        EndTextEditCurrentView();
         OUString aStr {ImpGetDescriptionString(bNoContortion ? STR_EditCrook : 
STR_EditCrookContortion)};
         if (bCopy)
             aStr+=SvxResId(STR_EditWithCopy);
@@ -666,7 +666,7 @@ void SdrEditView::DistortMarkedObj(const tools::Rectangle& 
rRef, const XPolygon&
 
     if( bUndo )
     {
-        EndTextEditAllViews();
+        EndTextEditCurrentView();
         OUString aStr {ImpGetDescriptionString(STR_EditDistort)};
         if (bCopy)
             aStr+=SvxResId(STR_EditWithCopy);
@@ -1111,7 +1111,7 @@ void SdrEditView::SetAttrToMarked(const SfxItemSet& 
rAttr, bool bReplaceAll)
     const bool bUndo = IsUndoEnabled();
     if( bUndo )
     {
-        EndTextEditAllViews();
+        EndTextEditCurrentView();
         BegUndo(ImpGetDescriptionString(STR_EditSetAttributes));
     }
 
@@ -1291,7 +1291,7 @@ void SdrEditView::SetStyleSheetToMarked(SfxStyleSheet* 
pStyleSheet, bool bDontRe
 
         if( bUndo )
         {
-            EndTextEditAllViews();
+            EndTextEditCurrentView();
             OUString aStr;
             if (pStyleSheet!=nullptr)
                 aStr = ImpGetDescriptionString(STR_EditSetStylesheet);
@@ -1859,7 +1859,7 @@ void SdrEditView::AlignMarkedObjects(SdrHorAlign eHor, 
SdrVertAlign eVert)
     const bool bUndo = IsUndoEnabled();
     if( bUndo )
     {
-        EndTextEditAllViews();
+        EndTextEditCurrentView();
         OUString aStr(GetDescriptionOfMarkedObjects());
         if (eHor==SdrHorAlign::NONE)
         {
diff --git a/svx/source/svdraw/svdedxv.cxx b/svx/source/svdraw/svdedxv.cxx
index 32d8ad82360b..32057e0b5163 100644
--- a/svx/source/svdraw/svdedxv.cxx
+++ b/svx/source/svdraw/svdedxv.cxx
@@ -1066,10 +1066,11 @@ IMPL_LINK(SdrObjEditView, ImpOutlinerCalcFieldValueHdl, 
EditFieldInfo*, pFI, voi
 
 IMPL_LINK_NOARG(SdrObjEditView, EndTextEditHdl, SdrUndoManager*, void) { 
SdrEndTextEdit(); }
 
-SdrUndoManager* SdrObjEditView::getSdrUndoManagerForEnhancedTextEdit() const
+// Default implementation - null UndoManager
+std::unique_ptr<SdrUndoManager> SdrObjEditView::createLocalTextUndoManager()
 {
-    // default returns registered UndoManager
-    return GetModel() ? 
dynamic_cast<SdrUndoManager*>(GetModel()->GetSdrUndoManager()) : nullptr;
+    SAL_WARN("svx", "SdrObjEditView::createLocalTextUndoManager needs to be 
overridden");
+    return std::unique_ptr<SdrUndoManager>();
 }
 
 bool SdrObjEditView::SdrBeginTextEdit(SdrObject* pObj_, SdrPageView* pPV, 
vcl::Window* pWin,
@@ -1370,7 +1371,11 @@ bool SdrObjEditView::SdrBeginTextEdit(SdrObject* pObj_, 
SdrPageView* pPV, vcl::W
             if (GetModel() && IsUndoEnabled()
                 && !GetModel()->GetDisableTextEditUsesCommonUndoManager())
             {
-                SdrUndoManager* pSdrUndoManager = 
getSdrUndoManagerForEnhancedTextEdit();
+                SdrUndoManager* pSdrUndoManager = nullptr;
+                mpLocalTextEditUndoManager = createLocalTextUndoManager();
+
+                if (mpLocalTextEditUndoManager)
+                    pSdrUndoManager = mpLocalTextEditUndoManager.get();
 
                 if (pSdrUndoManager)
                 {
@@ -1444,7 +1449,7 @@ SdrEndTextEditKind SdrObjEditView::SdrEndTextEdit(bool 
bDontDeleteReally)
         if (pOriginal)
         {
             // check if we got back our document undo manager
-            SdrUndoManager* pSdrUndoManager = 
getSdrUndoManagerForEnhancedTextEdit();
+            SdrUndoManager* pSdrUndoManager = mpLocalTextEditUndoManager.get();
 
             if (pSdrUndoManager && dynamic_cast<SdrUndoManager*>(pOriginal) == 
pSdrUndoManager)
             {
@@ -1476,6 +1481,8 @@ SdrEndTextEditKind SdrObjEditView::SdrEndTextEdit(bool 
bDontDeleteReally)
                                   "expected document UndoManager (!)");
                 delete pOriginal;
             }
+
+            mpLocalTextEditUndoManager.reset();
         }
     }
     else
diff --git a/sw/qa/extras/tiledrendering/data/shape.fodt 
b/sw/qa/extras/tiledrendering/data/shape.fodt
index feefe48bcde3..4e9a7f629ba4 100644
--- a/sw/qa/extras/tiledrendering/data/shape.fodt
+++ b/sw/qa/extras/tiledrendering/data/shape.fodt
@@ -1,5 +1,20 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<office:document 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:xlink="http://www.w3.org/1999/xlink"; 
xmlns:dc="http://purl.org/dc/elements/1.1/"; 
xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" 
xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" 
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" 
xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" 
xmlns:math="http://www.w3.org/1998/Math/MathML"; 
xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" 
xmlns:script="urn:oasis:names:tc:opendocument:xmlns:script:1.0" 
xmlns:config="urn:oas
 is:names:tc:opendocument:xmlns:config:1.0" 
xmlns:ooo="http://openoffice.org/2004/office"; 
xmlns:ooow="http://openoffice.org/2004/writer"; 
xmlns:oooc="http://openoffice.org/2004/calc"; 
xmlns:dom="http://www.w3.org/2001/xml-events"; 
xmlns:xforms="http://www.w3.org/2002/xforms"; 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"; 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xmlns:rpt="http://openoffice.org/2005/report"; 
xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" 
xmlns:xhtml="http://www.w3.org/1999/xhtml"; 
xmlns:grddl="http://www.w3.org/2003/g/data-view#"; 
xmlns:officeooo="http://openoffice.org/2009/office"; 
xmlns:tableooo="http://openoffice.org/2009/table"; 
xmlns:drawooo="http://openoffice.org/2010/draw"; 
xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0"
 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
 xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" 
xmlns:formx="urn:openoffice:names:
 experimental:ooxml-odf-interop:xmlns:form:1.0" 
xmlns:css3t="http://www.w3.org/TR/css3-text/"; office:version="1.2" 
office:mimetype="application/vnd.oasis.opendocument.text">
+
+<office:document xmlns:officeooo="http://openoffice.org/2009/office"; 
xmlns:css3t="http://www.w3.org/TR/css3-text/"; 
xmlns:grddl="http://www.w3.org/2003/g/data-view#"; 
xmlns:xhtml="http://www.w3.org/1999/xhtml"; 
xmlns:formx="urn:openoffice:names:experimental:ooxml-odf-interop:xmlns:form:1.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"; 
xmlns:xsd="http://www.w3.org/2001/XMLSchema"; 
xmlns:chart="urn:oasis:names:tc:opendocument:xmlns:chart:1.0" 
xmlns:svg="urn:oasis:names:tc:opendocument:xmlns:svg-compatible:1.0" 
xmlns:text="urn:oasis:names:tc:opendocument:xmlns:text:1.0" 
xmlns:oooc="http://openoffice.org/2004/calc"; 
xmlns:style="urn:oasis:names:tc:opendocument:xmlns:style:1.0" 
xmlns:ooow="http://openoffice.org/2004/writer"; 
xmlns:meta="urn:oasis:names:tc:opendocument:xmlns:meta:1.0" 
xmlns:dc="http://purl.org/dc/elements/1.1/"; 
xmlns:rpt="http://openoffice.org/2005/report"; 
xmlns:draw="urn:oasis:names:tc:opendocument:xmlns:drawing:1.0" 
xmlns:config="urn:oasis:names:tc:opendocument:xmlns
 :config:1.0" xmlns:xlink="http://www.w3.org/1999/xlink"; 
xmlns:fo="urn:oasis:names:tc:opendocument:xmlns:xsl-fo-compatible:1.0" 
xmlns:ooo="http://openoffice.org/2004/office"; 
xmlns:office="urn:oasis:names:tc:opendocument:xmlns:office:1.0" 
xmlns:dr3d="urn:oasis:names:tc:opendocument:xmlns:dr3d:1.0" 
xmlns:table="urn:oasis:names:tc:opendocument:xmlns:table:1.0" 
xmlns:number="urn:oasis:names:tc:opendocument:xmlns:datastyle:1.0" 
xmlns:of="urn:oasis:names:tc:opendocument:xmlns:of:1.2" 
xmlns:calcext="urn:org:documentfoundation:names:experimental:calc:xmlns:calcext:1.0"
 xmlns:tableooo="http://openoffice.org/2009/table"; 
xmlns:drawooo="http://openoffice.org/2010/draw"; 
xmlns:loext="urn:org:documentfoundation:names:experimental:office:xmlns:loext:1.0"
 xmlns:dom="http://www.w3.org/2001/xml-events"; 
xmlns:field="urn:openoffice:names:experimental:ooo-ms-interop:xmlns:field:1.0" 
xmlns:math="http://www.w3.org/1998/Math/MathML"; 
xmlns:form="urn:oasis:names:tc:opendocument:xmlns:form:1.0" xmlns:script="ur
 n:oasis:names:tc:opendocument:xmlns:script:1.0" 
xmlns:xforms="http://www.w3.org/2002/xforms"; office:version="1.3" 
office:mimetype="application/vnd.oasis.opendocument.text">
+ <office:styles>
+  <style:default-style style:family="graphic">
+   <style:graphic-properties svg:stroke-color="#3465a4" 
draw:fill-color="#729fcf" fo:wrap-option="no-wrap" draw:shadow-offset-x="0.3cm" 
draw:shadow-offset-y="0.3cm" draw:start-line-spacing-horizontal="0.283cm" 
draw:start-line-spacing-vertical="0.283cm" 
draw:end-line-spacing-horizontal="0.283cm" 
draw:end-line-spacing-vertical="0.283cm" style:flow-with-text="false"/>
+   <style:paragraph-properties style:text-autospace="ideograph-alpha" 
style:line-break="strict" style:writing-mode="lr-tb" 
style:font-independent-line-spacing="false">
+    <style:tab-stops/>
+   </style:paragraph-properties>
+   <style:text-properties style:use-window-font-color="true" 
loext:opacity="0%" style:font-name="Liberation Serif" fo:font-size="12pt" 
fo:language="en" fo:country="GB" style:letter-kerning="true" 
style:font-name-asian="Noto Serif CJK SC" style:font-size-asian="10.5pt" 
style:language-asian="zh" style:country-asian="CN" 
style:font-name-complex="Droid Sans Devanagari1" style:font-size-complex="12pt" 
style:language-complex="hi" style:country-complex="IN"/>
+  </style:default-style>
+ </office:styles>
+ <office:automatic-styles>
+  <style:style style:name="gr1" style:family="graphic">
+   <style:graphic-properties draw:textarea-horizontal-align="justify" 
draw:textarea-vertical-align="middle" draw:auto-grow-height="false" 
fo:min-height="1.9cm" fo:min-width="3.471cm" style:run-through="foreground" 
style:wrap="run-through" style:number-wrapped-paragraphs="no-limit" 
style:vertical-pos="from-top" style:vertical-rel="paragraph" 
style:horizontal-pos="from-left" style:horizontal-rel="paragraph"/>
+  </style:style>
+ </office:automatic-styles>
  <office:body>
   <office:text>
    <text:sequence-decls>
@@ -7,8 +22,9 @@
     <text:sequence-decl text:display-outline-level="0" text:name="Table"/>
     <text:sequence-decl text:display-outline-level="0" text:name="Text"/>
     <text:sequence-decl text:display-outline-level="0" text:name="Drawing"/>
+    <text:sequence-decl text:display-outline-level="0" text:name="Figure"/>
    </text:sequence-decls>
-   <text:p><draw:custom-shape text:anchor-type="paragraph" draw:z-index="0" 
svg:width="4.883cm" svg:height="3.225cm" svg:x="2.602cm" svg:y="1.178cm">
+   <text:p text:style-name="Standard"><draw:custom-shape 
text:anchor-type="paragraph" draw:z-index="0" draw:name="Shape1" 
draw:style-name="gr1" svg:width="4.908cm" svg:height="2.687cm" svg:x="1.575cm" 
svg:y="-0.132cm">
      <text:p/>
      <draw:enhanced-geometry svg:viewBox="0 0 21600 21600" 
draw:glue-points="10800 0 3163 3163 0 10800 3163 18437 10800 21600 18437 18437 
21600 10800 18437 3163" draw:text-areas="3163 3163 18437 18437" 
draw:type="ellipse" draw:enhanced-path="U 10800 10800 10800 10800 0 360 Z N"/>
     </draw:custom-shape>Hello.</text:p>
diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx 
b/sw/qa/extras/tiledrendering/tiledrendering.cxx
index 4994797328b8..9f7eca8b1241 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -1300,6 +1300,7 @@ void SwTiledRenderingTest::testUndoShapeLimiting()
     pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
     pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
     Scheduler::ProcessEventsToIdle();
+    pWrtShell2->EndTextEdit();
 
     // Assert that the first view can't and the second view can undo the 
insertion.
     SwDoc* pDoc = pXTextDocument->GetDocShell()->GetDoc();
@@ -1310,7 +1311,6 @@ void SwTiledRenderingTest::testUndoShapeLimiting()
     rUndoManager.SetView(&pWrtShell2->GetView());
     CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), 
rUndoManager.GetUndoActionCount());
 
-    pWrtShell2->EndTextEdit();
     rUndoManager.SetView(nullptr);
 
     SfxLokHelper::setView(nView1);
@@ -1418,11 +1418,14 @@ void SwTiledRenderingTest::testShapeTextUndoShells()
     pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0);
     pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0);
     Scheduler::ProcessEventsToIdle();
+    pWrtShell->EndTextEdit();
 
     // Make sure that the undo item remembers who created it.
     SwDoc* pDoc = pXTextDocument->GetDocShell()->GetDoc();
     sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
-    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), 
rUndoManager.GetUndoActionCount());
+    CPPUNIT_ASSERT_EQUAL(size_t(1), rUndoManager.GetUndoActionCount());
+    CPPUNIT_ASSERT_EQUAL(OUString("Edit text of Shape 'Shape1'"), 
rUndoManager.GetUndoActionComment(0));
+
     // This was -1: the view shell id for the undo action wasn't known.
     CPPUNIT_ASSERT_EQUAL(ViewShellId(nView1), 
rUndoManager.GetUndoAction()->GetViewShellId());
 }
@@ -1450,7 +1453,14 @@ void SwTiledRenderingTest::testShapeTextUndoGroupShells()
     // Make sure that the undo item remembers who created it.
     SwDoc* pDoc = pXTextDocument->GetDocShell()->GetDoc();
     sw::UndoManager& rUndoManager = pDoc->GetUndoManager();
-    CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), 
rUndoManager.GetUndoActionCount());
+    CPPUNIT_ASSERT_EQUAL(size_t(0), rUndoManager.GetUndoActionCount());
+
+    pWrtShell->EndTextEdit();
+    pWrtShell->GetView().BeginTextEdit(pObject, pView->GetSdrPageView(), 
pWrtShell->GetWin());
+
+    CPPUNIT_ASSERT_EQUAL(size_t(1), rUndoManager.GetUndoActionCount());
+    CPPUNIT_ASSERT_EQUAL(OUString("Edit text of Shape 'Shape1'"), 
rUndoManager.GetUndoActionComment(0));
+
     // This was -1: the view shell id for the (top) undo list action wasn't 
known.
     CPPUNIT_ASSERT_EQUAL(ViewShellId(nView1), 
rUndoManager.GetUndoAction()->GetViewShellId());
 
diff --git a/sw/source/core/draw/dview.cxx b/sw/source/core/draw/dview.cxx
index f9ef11b99897..ab69b7af2d68 100644
--- a/sw/source/core/draw/dview.cxx
+++ b/sw/source/core/draw/dview.cxx
@@ -984,12 +984,12 @@ void SwDrawView::DeleteMarked()
         pTmpRoot->EndAllAction();
 }
 
-// support enhanced text edit for draw objects
-SdrUndoManager* SwDrawView::getSdrUndoManagerForEnhancedTextEdit() const
+// Create a new view-local UndoManager manager for Writer
+std::unique_ptr<SdrUndoManager> SwDrawView::createLocalTextUndoManager()
 {
-    SwDoc* pDoc = Imp().GetShell()->GetDoc();
-
-    return pDoc ? dynamic_cast< SdrUndoManager* >(&(pDoc->GetUndoManager())) : 
nullptr;
+    std::unique_ptr<SdrUndoManager> pUndoManager(new SdrUndoManager);
+    pUndoManager->SetDocShell(SfxObjectShell::Current());
+    return pUndoManager;
 }
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/sw/source/core/inc/dview.hxx b/sw/source/core/inc/dview.hxx
index 2251efa48a76..4cd23aee519c 100644
--- a/sw/source/core/inc/dview.hxx
+++ b/sw/source/core/inc/dview.hxx
@@ -76,8 +76,8 @@ protected:
     using FmFormView::CheckSingleSdrObjectHit;
     virtual SdrObject* CheckSingleSdrObjectHit(const Point& rPnt, sal_uInt16 
nTol, SdrObject* pObj, SdrPageView* pPV, SdrSearchOptions nOptions, const 
SdrLayerIDSet* pMVisLay) const override;
 
-    // support enhanced text edit for draw objects
-    virtual SdrUndoManager* getSdrUndoManagerForEnhancedTextEdit() const 
override;
+    // Create a local UndoManager
+    std::unique_ptr<SdrUndoManager> createLocalTextUndoManager() override;
 
 public:
     SwDrawView(

Reply via email to