editeng/source/editeng/editview.cxx | 8 +++- editeng/source/editeng/impedit.cxx | 2 + include/editeng/outliner.hxx | 2 + include/sfx2/viewsh.hxx | 2 + sc/qa/unit/tiledrendering/tiledrendering.cxx | 1 sd/inc/undo/undomanager.hxx | 10 ++++- sd/qa/unit/tiledrendering/tiledrendering.cxx | 40 ++++++++++++++++++++ sd/source/core/undo/undomanager.cxx | 50 +++++++++++++++++++++++++ sd/source/ui/view/viewshe3.cxx | 11 +++++ sfx2/source/view/viewsh.cxx | 6 +++ sw/qa/extras/tiledrendering/tiledrendering.cxx | 44 ++++++++++++++++++++++ 11 files changed, 173 insertions(+), 3 deletions(-)
New commits: commit 5c99ed5f6524deb58f5a2ef4b91f69bfa0d21b25 Author: Miklos Vajna <vmik...@collabora.co.uk> Date: Wed Aug 17 07:53:16 2016 +0200 sd lok: limit undo/redo access to undo actions created by the same view Unlike in Writer, the state and the exec method of .uno:Undo is different codepath so for now ignore the Repair argument of the command, assuming that the command is only dispatched if the command is enabled. Change-Id: I3bfe8d72522f32efe436e21c383c99b3612eab6b (cherry picked from commit e0a3269183bf145511361a3968dca07824923dd4) diff --git a/sd/inc/undo/undomanager.hxx b/sd/inc/undo/undomanager.hxx index a020038..5c3a082 100644 --- a/sd/inc/undo/undomanager.hxx +++ b/sd/inc/undo/undomanager.hxx @@ -22,11 +22,14 @@ #include <misc/scopelock.hxx> #include <svx/sdrundomanager.hxx> +#include "sddllapi.h" + +class SfxViewShell; namespace sd { -class UndoManager : public SdrUndoManager +class SD_DLLPUBLIC UndoManager : public SdrUndoManager { public: UndoManager( sal_uInt16 nMaxUndoActionCount = 20 ); @@ -34,6 +37,9 @@ public: virtual void EnterListAction(const OUString &rComment, const OUString& rRepeatComment, sal_uInt16 nId, sal_Int32 nViewShellId) override; virtual void AddUndoAction( SfxUndoAction *pAction, bool bTryMerg=false ) override; + size_t GetUndoActionCount(const bool bCurrentLevel = true) const override; + size_t GetRedoActionCount(const bool bCurrentLevel = true) const override; + void SetViewShell(SfxViewShell* pViewShell); /** Set or reset the undo manager linked with the called undo manager. */ @@ -47,6 +53,8 @@ private: synchronize the undo managers. */ ::svl::IUndoManager* mpLinkedUndoManager; + /// Return undo/redo info for this view. + SfxViewShell* mpViewShell; /** Call ClearRedo() at the linked undo manager, when present. diff --git a/sd/qa/unit/tiledrendering/tiledrendering.cxx b/sd/qa/unit/tiledrendering/tiledrendering.cxx index 93c67d9..77f4ab1 100644 --- a/sd/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx @@ -69,6 +69,7 @@ public: void testViewCursorParts(); void testCursorViews(); void testViewLock(); + void testUndoLimiting(); CPPUNIT_TEST_SUITE(SdTiledRenderingTest); CPPUNIT_TEST(testRegisterCallback); @@ -93,6 +94,7 @@ public: CPPUNIT_TEST(testViewCursorParts); CPPUNIT_TEST(testCursorViews); CPPUNIT_TEST(testViewLock); + CPPUNIT_TEST(testUndoLimiting); CPPUNIT_TEST_SUITE_END(); private: @@ -1067,6 +1069,43 @@ void SdTiledRenderingTest::testViewLock() comphelper::LibreOfficeKit::setActive(false); } +void SdTiledRenderingTest::testUndoLimiting() +{ + comphelper::LibreOfficeKit::setActive(); + + // Create the first view. + SdXImpressDocument* pXImpressDocument = createDoc("title-shape.odp"); + SfxViewShell& rViewShell1 = pXImpressDocument->GetDocShell()->GetViewShell()->GetViewShellBase(); + SfxLokHelper::createView(); + pXImpressDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + SfxViewShell& rViewShell2 = pXImpressDocument->GetDocShell()->GetViewShell()->GetViewShellBase(); + + // Begin text edit on the only object on the slide. + sd::ViewShell* pViewShell = pXImpressDocument->GetDocShell()->GetViewShell(); + SdrView* pView = pViewShell->GetView(); + pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 0, awt::Key::TAB); + pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 0, awt::Key::TAB); + pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); + pXImpressDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); + Scheduler::ProcessEventsToIdle(); + CPPUNIT_ASSERT(pView->IsTextEdit()); + + // Now check what views see the undo action. + SdDrawDocument* pDocument = pXImpressDocument->GetDoc(); + sd::UndoManager* pUndoManager = pDocument->GetUndoManager(); + pUndoManager->SetViewShell(&rViewShell1); + // This was 1, undo action was visible to the first view, even if the + // action belongs to the second view. + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(0), pUndoManager->GetUndoActionCount()); + pUndoManager->SetViewShell(&rViewShell2); + CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(1), pUndoManager->GetUndoActionCount()); + pUndoManager->SetViewShell(nullptr); + + mxComponent->dispose(); + mxComponent.clear(); + comphelper::LibreOfficeKit::setActive(false); +} + CPPUNIT_TEST_SUITE_REGISTRATION(SdTiledRenderingTest); CPPUNIT_PLUGIN_IMPLEMENT(); diff --git a/sd/source/core/undo/undomanager.cxx b/sd/source/core/undo/undomanager.cxx index bbf2069..b0b9b68 100644 --- a/sd/source/core/undo/undomanager.cxx +++ b/sd/source/core/undo/undomanager.cxx @@ -17,6 +17,8 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <comphelper/lok.hxx> +#include <sfx2/viewsh.hxx> #include <undo/undomanager.hxx> using namespace sd; @@ -24,6 +26,7 @@ using namespace sd; UndoManager::UndoManager( sal_uInt16 nMaxUndoActionCount /* = 20 */ ) : SdrUndoManager( nMaxUndoActionCount ) , mpLinkedUndoManager(nullptr) + , mpViewShell(nullptr) { } @@ -49,6 +52,53 @@ void UndoManager::AddUndoAction( SfxUndoAction *pAction, bool bTryMerg /* = sal_ } } +size_t UndoManager::GetUndoActionCount(const bool bCurrentLevel) const +{ + size_t nRet = SdrUndoManager::GetUndoActionCount(bCurrentLevel); + if (!comphelper::LibreOfficeKit::isActive() || !mpViewShell) + return nRet; + + if (!nRet || !SdrUndoManager::GetUndoActionCount()) + return nRet; + + const SfxUndoAction* pAction = SdrUndoManager::GetUndoAction(); + if (!pAction) + return nRet; + + // If an other view created the last undo action, prevent undoing it from this view. + sal_Int32 nViewShellId = mpViewShell->GetViewShellId(); + if (pAction->GetViewShellId() != nViewShellId) + nRet = 0; + + return nRet; +} + +size_t UndoManager::GetRedoActionCount(const bool bCurrentLevel) const +{ + size_t nRet = SdrUndoManager::GetRedoActionCount(bCurrentLevel); + if (!comphelper::LibreOfficeKit::isActive() || !mpViewShell) + return nRet; + + if (!nRet || !SdrUndoManager::GetRedoActionCount()) + return nRet; + + const SfxUndoAction* pAction = SdrUndoManager::GetRedoAction(); + if (!pAction) + return nRet; + + // If an other view created the first redo action, prevent redoing it from this view. + sal_Int32 nViewShellId = mpViewShell->GetViewShellId(); + if (pAction->GetViewShellId() != nViewShellId) + nRet = 0; + + return nRet; +} + +void UndoManager::SetViewShell(SfxViewShell* pViewShell) +{ + mpViewShell = pViewShell; +} + void UndoManager::SetLinkedUndoManager (::svl::IUndoManager* pLinkedUndoManager) { mpLinkedUndoManager = pLinkedUndoManager; diff --git a/sd/source/ui/view/viewshe3.cxx b/sd/source/ui/view/viewshe3.cxx index a10aae8..b9e0987 100644 --- a/sd/source/ui/view/viewshe3.cxx +++ b/sd/source/ui/view/viewshe3.cxx @@ -71,6 +71,7 @@ #include "framework/FrameworkHelper.hxx" #include "optsitem.hxx" #include "sdresid.hxx" +#include "undo/undomanager.hxx" #include <svx/svxids.hrc> #include <sfx2/request.hxx> @@ -130,10 +131,15 @@ void ViewShell::GetMenuState( SfxItemSet &rSet ) if(pUndoManager) { + auto pSdUndoManager = dynamic_cast<sd::UndoManager*>(pUndoManager); + if (pSdUndoManager) + pSdUndoManager->SetViewShell(&GetViewShellBase()); if(pUndoManager->GetUndoActionCount() != 0) { bActivate = true; } + if (pSdUndoManager) + pSdUndoManager->SetViewShell(nullptr); } if(bActivate) @@ -157,10 +163,15 @@ void ViewShell::GetMenuState( SfxItemSet &rSet ) if(pUndoManager) { + auto pSdUndoManager = dynamic_cast<sd::UndoManager*>(pUndoManager); + if (pSdUndoManager) + pSdUndoManager->SetViewShell(&GetViewShellBase()); if(pUndoManager->GetRedoActionCount() != 0) { bActivate = true; } + if (pSdUndoManager) + pSdUndoManager->SetViewShell(nullptr); } if(bActivate) commit 5e04584d20629e84c6c9446032caba77ef596791 Author: Miklos Vajna <vmik...@collabora.co.uk> Date: Tue Aug 16 13:58:50 2016 +0200 LOK unit tests: document what is a view callback Reviewed-on: https://gerrit.libreoffice.org/28168 Reviewed-by: Miklos Vajna <vmik...@collabora.co.uk> Tested-by: Jenkins <c...@libreoffice.org> (cherry picked from commit c3c5635b9bbd3de65760409c7f4e72b295b749be) Conflicts: sc/qa/unit/tiledrendering/tiledrendering.cxx Change-Id: Ic605ca12cebfb6fd8239829942bbc6a70f45ac06 diff --git a/sc/qa/unit/tiledrendering/tiledrendering.cxx b/sc/qa/unit/tiledrendering/tiledrendering.cxx index 8b088ba..e738807 100644 --- a/sc/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sc/qa/unit/tiledrendering/tiledrendering.cxx @@ -348,6 +348,7 @@ void ScTiledRenderingTest::testDocumentSize() comphelper::LibreOfficeKit::setActive(false); } +/// A view callback tracks callbacks invoked on one specific view. class ViewCallback { public: diff --git a/sd/qa/unit/tiledrendering/tiledrendering.cxx b/sd/qa/unit/tiledrendering/tiledrendering.cxx index ba1cb84..93c67d9 100644 --- a/sd/qa/unit/tiledrendering/tiledrendering.cxx +++ b/sd/qa/unit/tiledrendering/tiledrendering.cxx @@ -851,6 +851,7 @@ void SdTiledRenderingTest::testResizeTableColumn() comphelper::LibreOfficeKit::setActive(false); } +/// A view callback tracks callbacks invoked on one specific view. class ViewCallback { public: diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx index ce99ddc..0111948 100644 --- a/sw/qa/extras/tiledrendering/tiledrendering.cxx +++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx @@ -572,6 +572,7 @@ void SwTiledRenderingTest::testPartHash() comphelper::LibreOfficeKit::setActive(false); } +/// A view callback tracks callbacks invoked on one specific view. class ViewCallback { public: commit feffeb503457c369e7d12b5ce151b6b588192e14 Author: Miklos Vajna <vmik...@collabora.co.uk> Date: Tue Aug 16 12:34:12 2016 +0200 editeng: introduce OutlinerViewShell::NotifyOtherViews() This allows notifying other views about e.g. cursor position changes even if SfxLokHelper::notifyOtherViews() is not accessible from editeng. Change-Id: I921e97344ffe562109a221f241e70b3f68ee9aaf Reviewed-on: https://gerrit.libreoffice.org/28162 Reviewed-by: Miklos Vajna <vmik...@collabora.co.uk> Tested-by: Jenkins <c...@libreoffice.org> (cherry picked from commit 77235ac64be61afd707931675fec100c7c50d01c) diff --git a/editeng/source/editeng/editview.cxx b/editeng/source/editeng/editview.cxx index 8dea0b8..5d64e4f 100644 --- a/editeng/source/editeng/editview.cxx +++ b/editeng/source/editeng/editview.cxx @@ -404,7 +404,9 @@ void EditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor, bool bActivat if (pImpEditView->mpViewShell && !bActivate) { - pImpEditView->mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, OString::boolean(true).getStr()); + OString aPayload = OString::boolean(true); + pImpEditView->mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload.getStr()); + pImpEditView->mpViewShell->NotifyOtherViews(LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible", aPayload); } } } @@ -415,7 +417,9 @@ void EditView::HideCursor(bool bDeactivate) if (pImpEditView->mpViewShell && !bDeactivate) { - pImpEditView->mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, OString::boolean(false).getStr()); + OString aPayload = OString::boolean(false); + pImpEditView->mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_CURSOR_VISIBLE, aPayload.getStr()); + pImpEditView->mpViewShell->NotifyOtherViews(LOK_CALLBACK_VIEW_CURSOR_VISIBLE, "visible", aPayload); } } diff --git a/editeng/source/editeng/impedit.cxx b/editeng/source/editeng/impedit.cxx index 01972d3..795a824 100644 --- a/editeng/source/editeng/impedit.cxx +++ b/editeng/source/editeng/impedit.cxx @@ -407,6 +407,7 @@ void ImpEditView::DrawSelection( EditSelection aTmpSel, vcl::Region* pRegion, Ou } mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_TEXT_SELECTION, sRectangle.getStr()); + mpViewShell->NotifyOtherViews(LOK_CALLBACK_TEXT_VIEW_SELECTION, "selection", sRectangle); pOutWin->Pop(); } @@ -1004,6 +1005,7 @@ void ImpEditView::ShowCursor( bool bGotoCursor, bool bForceVisCursor ) OString sRect = aRect.toString(); mpViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_VISIBLE_CURSOR, sRect.getStr()); + mpViewShell->NotifyOtherViews(LOK_CALLBACK_INVALIDATE_VIEW_CURSOR, "rectangle", sRect); } CursorDirection nCursorDir = CursorDirection::NONE; diff --git a/include/editeng/outliner.hxx b/include/editeng/outliner.hxx index 52383ac..171b8d0 100644 --- a/include/editeng/outliner.hxx +++ b/include/editeng/outliner.hxx @@ -382,6 +382,8 @@ class SAL_NO_VTABLE SAL_DLLPUBLIC_RTTI OutlinerViewShell public: virtual void libreOfficeKitViewCallback(int nType, const char* pPayload) const = 0; virtual sal_uInt32 GetViewShellId() const = 0; + /// Wrapper around SfxLokHelper::notifyOtherViews(). + virtual void NotifyOtherViews(int nType, const OString& rKey, const OString& rPayload) = 0; protected: ~OutlinerViewShell() throw () {} diff --git a/include/sfx2/viewsh.hxx b/include/sfx2/viewsh.hxx index 03b696c..e4b21a2 100644 --- a/include/sfx2/viewsh.hxx +++ b/include/sfx2/viewsh.hxx @@ -336,6 +336,8 @@ public: virtual void dumpAsXml(struct _xmlTextWriter* pWriter) const; /// See OutlinerViewShell::GetViewShellId(). sal_uInt32 GetViewShellId() const override; + /// See OutlinerViewShell::NotifyOtherViews(). + void NotifyOtherViews(int nType, const OString& rKey, const OString& rPayload) override; }; diff --git a/sfx2/source/view/viewsh.cxx b/sfx2/source/view/viewsh.cxx index c8ce31a..e711099 100644 --- a/sfx2/source/view/viewsh.cxx +++ b/sfx2/source/view/viewsh.cxx @@ -81,6 +81,7 @@ #include "workwin.hxx" #include <sfx2/objface.hxx> #include <sfx2/docfilt.hxx> +#include <sfx2/lokhelper.hxx> #include "openuriexternally.hxx" #include <shellimpl.hxx> @@ -1657,6 +1658,11 @@ sal_uInt32 SfxViewShell::GetViewShellId() const return pImp->m_nViewShellId; } +void SfxViewShell::NotifyOtherViews(int nType, const OString& rKey, const OString& rPayload) +{ + SfxLokHelper::notifyOtherViews(this, nType, rKey, rPayload); +} + void SfxViewShell::dumpAsXml(xmlTextWriterPtr pWriter) const { xmlTextWriterStartElement(pWriter, BAD_CAST("sfxViewShell")); diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx index 72f6f1c..ce99ddc 100644 --- a/sw/qa/extras/tiledrendering/tiledrendering.cxx +++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx @@ -55,6 +55,7 @@ public: void testPageDownInvalidation(); void testPartHash(); void testViewCursors(); + void testShapeViewCursors(); void testMissingInvalidation(); void testViewCursorVisibility(); void testViewCursorCleanup(); @@ -86,6 +87,7 @@ public: CPPUNIT_TEST(testPageDownInvalidation); CPPUNIT_TEST(testPartHash); CPPUNIT_TEST(testViewCursors); + CPPUNIT_TEST(testShapeViewCursors); CPPUNIT_TEST(testMissingInvalidation); CPPUNIT_TEST(testViewCursorVisibility); CPPUNIT_TEST(testViewCursorCleanup); @@ -736,6 +738,47 @@ void SwTiledRenderingTest::testViewCursors() comphelper::LibreOfficeKit::setActive(false); } +void SwTiledRenderingTest::testShapeViewCursors() +{ + comphelper::LibreOfficeKit::setActive(); + + // Load a document and create a view, so we have 2 ones. + SwXTextDocument* pXTextDocument = createDoc("shape.fodt"); + ViewCallback aView1; + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView1); + SfxLokHelper::createView(); + ViewCallback aView2; + pXTextDocument->initializeForTiledRendering(uno::Sequence<beans::PropertyValue>()); + SfxViewShell::Current()->registerLibreOfficeKitViewCallback(&ViewCallback::callback, &aView2); + SwWrtShell* pWrtShell2 = pXTextDocument->GetDocShell()->GetWrtShell(); + + // Start shape text in the second view. + SdrPage* pPage = pWrtShell2->GetDoc()->getIDocumentDrawModelAccess().GetDrawModel()->GetPage(0); + SdrObject* pObject = pPage->GetObj(0); + SdrView* pView = pWrtShell2->GetDrawView(); + pWrtShell2->GetView().BeginTextEdit(pObject, pView->GetSdrPageView(), pWrtShell2->GetWin()); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'x', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'x', 0); + + // Press a key in the second view, while the first one observes this. + aView1.m_bOwnCursorInvalidated = false; + aView1.m_bViewCursorInvalidated = false; + aView2.m_bOwnCursorInvalidated = false; + aView2.m_bViewCursorInvalidated = false; + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYINPUT, 'y', 0); + pXTextDocument->postKeyEvent(LOK_KEYEVENT_KEYUP, 'y', 0); + // Make sure that aView1 gets a view-only cursor notification, while + // aView2 gets a real cursor notification. + CPPUNIT_ASSERT(!aView1.m_bOwnCursorInvalidated); + CPPUNIT_ASSERT(aView1.m_bViewCursorInvalidated); + CPPUNIT_ASSERT(aView2.m_bOwnCursorInvalidated); + CPPUNIT_ASSERT(!aView2.m_bViewCursorInvalidated); + mxComponent->dispose(); + mxComponent.clear(); + + comphelper::LibreOfficeKit::setActive(false); +} + void SwTiledRenderingTest::testViewCursorVisibility() { comphelper::LibreOfficeKit::setActive(); _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits