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/uitest/impress_tests/tdf130440.py           |   19 +
 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                     |   12 
 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 
 19 files changed, 476 insertions(+), 65 deletions(-)

New commits:
commit 2d95b3846eac367d2baadc194ab258dc31e7bd33
Author:     Tomaž Vajngerl <[email protected]>
AuthorDate: Thu Oct 7 16:48:46 2021 +0200
Commit:     Tomaž Vajngerl <[email protected]>
CommitDate: Fri Oct 22 22:02:00 2021 +0200

    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.
    
    Change-Id: I04edb4f91d7e111a490c946f7121cbca75f818d7
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123220
    Tested-by: Tomaž Vajngerl <[email protected]>
    Reviewed-by: Tomaž Vajngerl <[email protected]>
    (cherry picked from commit c175c1dc19d0edc8ca66e39f0b4b8af04e3d6c87)
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/123951

diff --git a/include/svx/svdedtv.hxx b/include/svx/svdedtv.hxx
index 001223425a44..cf9955edcb15 100644
--- a/include/svx/svdedtv.hxx
+++ b/include/svx/svdedtv.hxx
@@ -188,6 +188,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 8befc36dfb7c..1741828b2e62 100644
--- a/include/svx/svdedxv.hxx
+++ b/include/svx/svdedxv.hxx
@@ -107,18 +107,15 @@ protected:
 
 private:
     SfxUndoManager* mpOldTextEditUndoManager;
+    std::unique_ptr<SdrUndoManager> mpLocalTextEditUndoManager;
 
 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.
@@ -178,6 +175,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 c484a76e5bef..dfff2fbe2a69 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 c589e661e88c..43704c80e17d 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 dynamic_cast<SdrUndoManager*>(rDoc.GetUndoManager());
+    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/uitest/impress_tests/tdf130440.py 
b/sd/qa/uitest/impress_tests/tdf130440.py
index 348feb33c0fa..b242052cff95 100644
--- a/sd/qa/uitest/impress_tests/tdf130440.py
+++ b/sd/qa/uitest/impress_tests/tdf130440.py
@@ -25,24 +25,43 @@ class tdf129346(UITestCase):
 
         xDoc = self.xUITest.getTopFocusWindow()
         xEdit = xDoc.getChild("impress_win")
+        # Type "test" into the text box
         xEdit.executeAction("TYPE", mkPropertyValues({"TEXT":"test"}))
+        xToolkit.processEventsToIdle()
+
+        # Rename the slide to interrupt the text edit mode
+        self.ui_test.execute_dialog_through_command(".uno:RenamePage")
+        xDialog = self.xUITest.getTopFocusWindow()
+        name_entry = xDialog.getChild("name_entry")
+        name_entry.executeAction("TYPE", mkPropertyValues({"TEXT":"NewName"}))
+        xOKBtn = xDialog.getChild("ok")
+        self.ui_test.close_dialog_through_button(xOKBtn)
+        xToolkit.processEventsToIdle()
+
+        # We should be at Page 2
+        self.assertEqual(document.CurrentController.getCurrentPage().Number, 2)
 
+        # Undo the renaming of the page
         self.xUITest.executeCommand(".uno:Undo")
         xToolkit.processEventsToIdle()
         self.assertEqual(document.CurrentController.getCurrentPage().Number, 2)
 
+        # Undo the text edit
         self.xUITest.executeCommand(".uno:Undo")
         xToolkit.processEventsToIdle()
         self.assertEqual(document.CurrentController.getCurrentPage().Number, 2)
 
+        # Undo sends us to page 1 and undo-es command ".uno:DuplicatePage"
         self.xUITest.executeCommand(".uno:Undo")
         xToolkit.processEventsToIdle()
         self.assertEqual(document.CurrentController.getCurrentPage().Number, 1)
 
+        # Redo ".uno:DuplicatePage" - we go to Page 2
         self.xUITest.executeCommand(".uno:Redo")
         xToolkit.processEventsToIdle()
         self.assertEqual(document.CurrentController.getCurrentPage().Number, 2)
 
+        # Redo text edit
         self.xUITest.executeCommand(".uno:Redo")
 
         xDoc = self.xUITest.getTopFocusWindow()
diff --git a/sd/qa/unit/misc-tests.cxx b/sd/qa/unit/misc-tests.cxx
index 82734af9eb73..53980abeafcb 100644
--- a/sd/qa/unit/misc-tests.cxx
+++ b/sd/qa/unit/misc-tests.cxx
@@ -71,7 +71,7 @@ public:
     void testTdf96206();
     void testTdf96708();
     void testTdf99396();
-    void testTdf99396TextEdit();
+    void testTableObjectUndoTest();
     void testFillGradient();
     void testTdf44774();
     void testTdf38225();
@@ -94,7 +94,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);
@@ -271,8 +271,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();
@@ -298,14 +300,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();
@@ -323,6 +337,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();
@@ -338,6 +356,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
@@ -348,8 +369,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 63c8a75e0d96..8d9a23afaa5b 100644
--- a/sd/qa/unit/tiledrendering/tiledrendering.cxx
+++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx
@@ -134,6 +134,7 @@ public:
     void testSlideDuplicateUndo();
     void testMoveShapeHandle();
     void testDeleteTable();
+    void testShapeEditInMultipleViews();
 
     CPPUNIT_TEST_SUITE(SdTiledRenderingTest);
     CPPUNIT_TEST(testCreateDestroy);
@@ -191,7 +192,7 @@ public:
     CPPUNIT_TEST(testSlideDuplicateUndo);
     CPPUNIT_TEST(testMoveShapeHandle);
     CPPUNIT_TEST(testDeleteTable);
-
+    CPPUNIT_TEST(testShapeEditInMultipleViews);
     CPPUNIT_TEST_SUITE_END();
 
 private:
@@ -1326,6 +1327,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());
@@ -2063,11 +2096,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;
@@ -2082,15 +2123,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.
@@ -2101,15 +2151,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()));
     }
 }
 
@@ -2126,17 +2184,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());
     }
 
@@ -2148,16 +2209,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());
     }
 }
@@ -2677,7 +2745,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 06462ecdf75c..2231bfcc3ac8 100644
--- a/sd/source/ui/view/drviews1.cxx
+++ b/sd/source/ui/view/drviews1.cxx
@@ -344,7 +344,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 5a2a0be72ce7..7f30d85f2c77 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>
 
@@ -623,6 +625,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 6f6ac53a11fa..ee6dae66d985 100644
--- a/svx/source/svdraw/svddrgmt.cxx
+++ b/svx/source/svdraw/svddrgmt.cxx
@@ -1352,7 +1352,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 2fd71bee4092..6f2be8bf54f4 100644
--- a/svx/source/svdraw/svdedtv.cxx
+++ b/svx/source/svdraw/svdedtv.cxx
@@ -998,7 +998,7 @@ bool SdrEditView::InsertObjectAtView(SdrObject* pObj, 
SdrPageView& rPV, SdrInser
     }
     if( IsUndoEnabled())
     {
-        EndTextEditAllViews();
+        EndTextEditCurrentView();
         AddUndo(GetModel()->GetSdrUndoFactory().CreateUndoNewObject(*pObj));
     }
 
@@ -1069,4 +1069,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 50a903b0a4b5..d785af007144 100644
--- a/svx/source/svdraw/svdedtv1.cxx
+++ b/svx/source/svdraw/svdedtv1.cxx
@@ -94,7 +94,7 @@ void SdrEditView::SetMarkedObjRect(const tools::Rectangle& 
rRect)
     const bool bUndo = IsUndoEnabled();
     if( bUndo )
     {
-        EndTextEditAllViews();
+        EndTextEditCurrentView();
         BegUndo(ImpGetDescriptionString(STR_EditPosSize));
     }
 
@@ -185,7 +185,7 @@ void SdrEditView::MoveMarkedObj(const Size& rSiz, bool 
bCopy)
 
     if( bUndo )
     {
-        EndTextEditAllViews();
+        EndTextEditCurrentView();
         OUString aStr(SvxResId(STR_EditMove));
         if (bCopy)
             aStr += SvxResId(STR_EditWithCopy);
@@ -218,7 +218,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);
@@ -253,7 +253,7 @@ void SdrEditView::ResizeMultMarkedObj(const Point& rRef,
     const bool bUndo = IsUndoEnabled();
     if( bUndo )
     {
-        EndTextEditAllViews();
+        EndTextEditCurrentView();
         BegUndo(ImpGetDescriptionString(STR_EditResize));
     }
 
@@ -300,7 +300,7 @@ void SdrEditView::RotateMarkedObj(const Point& rRef, 
tools::Long nAngle, bool bC
     const bool bUndo = IsUndoEnabled();
     if( bUndo )
     {
-        EndTextEditAllViews();
+        EndTextEditCurrentView();
         OUString aStr {ImpGetDescriptionString(STR_EditRotate)};
         if (bCopy) aStr+=SvxResId(STR_EditWithCopy);
         BegUndo(aStr);
@@ -357,7 +357,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)
@@ -457,7 +457,7 @@ void SdrEditView::ShearMarkedObj(const Point& rRef, 
tools::Long nAngle, bool bVS
 
     if( bUndo )
     {
-        EndTextEditAllViews();
+        EndTextEditCurrentView();
         OUString aStr {ImpGetDescriptionString(STR_EditShear)};
         if (bCopy)
             aStr+=SvxResId(STR_EditWithCopy);
@@ -573,7 +573,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);
@@ -647,7 +647,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);
@@ -1097,7 +1097,7 @@ void SdrEditView::SetAttrToMarked(const SfxItemSet& 
rAttr, bool bReplaceAll)
     const bool bUndo = IsUndoEnabled();
     if( bUndo )
     {
-        EndTextEditAllViews();
+        EndTextEditCurrentView();
         BegUndo(ImpGetDescriptionString(STR_EditSetAttributes));
     }
 
@@ -1276,7 +1276,7 @@ void SdrEditView::SetStyleSheetToMarked(SfxStyleSheet* 
pStyleSheet, bool bDontRe
 
     if( bUndo )
     {
-        EndTextEditAllViews();
+        EndTextEditCurrentView();
         OUString aStr;
         if (pStyleSheet!=nullptr)
             aStr = ImpGetDescriptionString(STR_EditSetStylesheet);
@@ -1843,7 +1843,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 65aadab57145..a4d43f97b8c6 100644
--- a/svx/source/svdraw/svdedxv.cxx
+++ b/svx/source/svdraw/svdedxv.cxx
@@ -1057,10 +1057,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,
@@ -1357,7 +1358,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)
                 {
@@ -1431,7 +1436,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)
             {
@@ -1464,6 +1469,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 e78c91d7370d..a9aa0b63cc7c 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -1306,6 +1306,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();
@@ -1316,7 +1317,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);
@@ -1421,11 +1421,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());
 }
@@ -1452,7 +1455,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 3f00c8613294..84357fcfbff1 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