diff options
-rw-r--r-- | desktop/inc/lib/init.hxx | 3 | ||||
-rw-r--r-- | desktop/qa/desktop_lib/test_desktop_lib.cxx | 100 | ||||
-rw-r--r-- | desktop/source/lib/init.cxx | 36 | ||||
-rw-r--r-- | include/editeng/outliner.hxx | 1 | ||||
-rw-r--r-- | include/sfx2/lokhelper.hxx | 17 | ||||
-rw-r--r-- | include/sfx2/viewsh.hxx | 15 | ||||
-rw-r--r-- | sc/source/ui/view/tabvwshc.cxx | 3 | ||||
-rw-r--r-- | sd/qa/unit/tiledrendering/LOKitSearchTest.cxx | 1 | ||||
-rw-r--r-- | sd/source/ui/unoidl/unomodel.cxx | 3 | ||||
-rw-r--r-- | sfx2/source/view/lokhelper.cxx | 120 | ||||
-rw-r--r-- | sfx2/source/view/viewimp.hxx | 4 | ||||
-rw-r--r-- | sfx2/source/view/viewsh.cxx | 13 | ||||
-rw-r--r-- | sw/qa/extras/tiledrendering/tiledrendering.cxx | 2 |
13 files changed, 249 insertions, 69 deletions
diff --git a/desktop/inc/lib/init.hxx b/desktop/inc/lib/init.hxx index a71ecae79f83..84d9d5299fd4 100644 --- a/desktop/inc/lib/init.hxx +++ b/desktop/inc/lib/init.hxx @@ -150,7 +150,8 @@ namespace desktop { std::map<size_t, std::shared_ptr<CallbackFlushHandler>> mpCallbackFlushHandlers; const int mnDocumentId; - explicit LibLODocument_Impl(const css::uno::Reference <css::lang::XComponent> &xComponent, int nDocumentId = -1); + explicit LibLODocument_Impl(const css::uno::Reference<css::lang::XComponent>& xComponent, + int nDocumentId); ~LibLODocument_Impl(); }; diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx index a02347450a38..0a19d5582e80 100644 --- a/desktop/qa/desktop_lib/test_desktop_lib.cxx +++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx @@ -195,6 +195,7 @@ public: void testCalcSaveAs(); void testControlState(); void testMetricField(); + void testMultiDocuments(); void testABI(); CPPUNIT_TEST_SUITE(DesktopLOKTest); @@ -257,6 +258,7 @@ public: CPPUNIT_TEST(testCalcSaveAs); CPPUNIT_TEST(testControlState); CPPUNIT_TEST(testMetricField); + CPPUNIT_TEST(testMultiDocuments); CPPUNIT_TEST(testABI); CPPUNIT_TEST_SUITE_END(); @@ -322,10 +324,13 @@ DesktopLOKTest::loadDocUrlImpl(const OUString& rFileURL, LibreOfficeKitDocumentT break; } + static int nDocumentIdCounter = 0; + SfxViewShell::SetCurrentDocId(ViewShellDocId(nDocumentIdCounter)); uno::Reference<lang::XComponent> xComponent = loadFromDesktop(rFileURL, aService); CPPUNIT_ASSERT(xComponent.is()); - std::unique_ptr<LibLODocument_Impl> pDocument(new LibLODocument_Impl(xComponent)); + std::unique_ptr<LibLODocument_Impl> pDocument(new LibLODocument_Impl(xComponent, nDocumentIdCounter)); + ++nDocumentIdCounter; return std::make_pair(std::move(pDocument), xComponent); } @@ -2933,6 +2938,99 @@ void DesktopLOKTest::testSpellcheckerMultiView() CPPUNIT_ASSERT_EQUAL(1, pDocument->m_pDocumentClass->getViewsCount(pDocument)); } +void DesktopLOKTest::testMultiDocuments() +{ + // Load a document. + uno::Reference<lang::XComponent> xComponent1; + std::unique_ptr<LibLODocument_Impl> document1; + std::tie(document1, xComponent1) = loadDocImpl("blank_text.odt"); + LibLODocument_Impl* pDocument1 = document1.get(); + CPPUNIT_ASSERT_EQUAL(1, pDocument1->m_pDocumentClass->getViewsCount(pDocument1)); + const int nDocId1 = pDocument1->mnDocumentId; + + const int nDoc1View0 = pDocument1->m_pDocumentClass->getView(pDocument1); + CPPUNIT_ASSERT_EQUAL(nDocId1, SfxLokHelper::getDocumentIdOfView(nDoc1View0)); + const int nDoc1View1 = pDocument1->m_pDocumentClass->createView(pDocument1); + CPPUNIT_ASSERT_EQUAL(nDoc1View1, pDocument1->m_pDocumentClass->getView(pDocument1)); + CPPUNIT_ASSERT_EQUAL(nDocId1, SfxLokHelper::getDocumentIdOfView(nDoc1View1)); + CPPUNIT_ASSERT_EQUAL(2, pDocument1->m_pDocumentClass->getViewsCount(pDocument1)); + + // Validate the views of document 1. + std::vector<int> aViewIdsDoc1(2); + CPPUNIT_ASSERT(pDocument1->m_pDocumentClass->getViewIds(pDocument1, aViewIdsDoc1.data(), aViewIdsDoc1.size())); + CPPUNIT_ASSERT_EQUAL(nDoc1View0, aViewIdsDoc1[0]); + CPPUNIT_ASSERT_EQUAL(nDoc1View1, aViewIdsDoc1[1]); + + CPPUNIT_ASSERT_EQUAL(nDoc1View1, pDocument1->m_pDocumentClass->getView(pDocument1)); + CPPUNIT_ASSERT_EQUAL(nDocId1, SfxLokHelper::getDocumentIdOfView(nDoc1View1)); + pDocument1->m_pDocumentClass->setView(pDocument1, nDoc1View0); + CPPUNIT_ASSERT_EQUAL(nDoc1View0, pDocument1->m_pDocumentClass->getView(pDocument1)); + CPPUNIT_ASSERT_EQUAL(nDocId1, SfxLokHelper::getDocumentIdOfView(nDoc1View0)); + pDocument1->m_pDocumentClass->setView(pDocument1, nDoc1View1); + CPPUNIT_ASSERT_EQUAL(nDoc1View1, pDocument1->m_pDocumentClass->getView(pDocument1)); + CPPUNIT_ASSERT_EQUAL(nDocId1, SfxLokHelper::getDocumentIdOfView(nDoc1View1)); + CPPUNIT_ASSERT_EQUAL(2, pDocument1->m_pDocumentClass->getViewsCount(pDocument1)); + + // Load another document. + uno::Reference<lang::XComponent> xComponent2; + std::unique_ptr<LibLODocument_Impl> document2; + std::tie(document2, xComponent2) = loadDocImpl("blank_presentation.odp"); + LibLODocument_Impl* pDocument2 = document2.get(); + CPPUNIT_ASSERT_EQUAL(1, pDocument2->m_pDocumentClass->getViewsCount(pDocument2)); + const int nDocId2 = pDocument2->mnDocumentId; + + const int nDoc2View0 = pDocument2->m_pDocumentClass->getView(pDocument2); + CPPUNIT_ASSERT_EQUAL(nDocId2, SfxLokHelper::getDocumentIdOfView(nDoc2View0)); + const int nDoc2View1 = pDocument2->m_pDocumentClass->createView(pDocument2); + CPPUNIT_ASSERT_EQUAL(nDoc2View1, pDocument2->m_pDocumentClass->getView(pDocument2)); + CPPUNIT_ASSERT_EQUAL(nDocId2, SfxLokHelper::getDocumentIdOfView(nDoc2View1)); + CPPUNIT_ASSERT_EQUAL(2, pDocument2->m_pDocumentClass->getViewsCount(pDocument2)); + + // Validate the views of document 2. + std::vector<int> aViewIdsDoc2(2); + CPPUNIT_ASSERT(pDocument2->m_pDocumentClass->getViewIds(pDocument2, aViewIdsDoc2.data(), aViewIdsDoc2.size())); + CPPUNIT_ASSERT_EQUAL(nDoc2View0, aViewIdsDoc2[0]); + CPPUNIT_ASSERT_EQUAL(nDoc2View1, aViewIdsDoc2[1]); + + CPPUNIT_ASSERT_EQUAL(nDoc2View1, pDocument2->m_pDocumentClass->getView(pDocument2)); + CPPUNIT_ASSERT_EQUAL(nDocId2, SfxLokHelper::getDocumentIdOfView(nDoc2View1)); + pDocument2->m_pDocumentClass->setView(pDocument2, nDoc2View0); + CPPUNIT_ASSERT_EQUAL(nDoc2View0, pDocument2->m_pDocumentClass->getView(pDocument2)); + CPPUNIT_ASSERT_EQUAL(nDocId2, SfxLokHelper::getDocumentIdOfView(nDoc2View0)); + pDocument2->m_pDocumentClass->setView(pDocument2, nDoc2View1); + CPPUNIT_ASSERT_EQUAL(nDoc2View1, pDocument2->m_pDocumentClass->getView(pDocument2)); + CPPUNIT_ASSERT_EQUAL(nDocId2, SfxLokHelper::getDocumentIdOfView(nDoc2View1)); + CPPUNIT_ASSERT_EQUAL(2, pDocument2->m_pDocumentClass->getViewsCount(pDocument2)); + + // The views of document1 should be unchanged. + CPPUNIT_ASSERT(pDocument1->m_pDocumentClass->getViewIds(pDocument1, aViewIdsDoc1.data(), aViewIdsDoc1.size())); + CPPUNIT_ASSERT_EQUAL(nDoc1View0, aViewIdsDoc1[0]); + CPPUNIT_ASSERT_EQUAL(nDoc1View1, aViewIdsDoc1[1]); + // Switch views in the first doc. + CPPUNIT_ASSERT_EQUAL(nDocId1, SfxLokHelper::getDocumentIdOfView(nDoc1View0)); + pDocument1->m_pDocumentClass->setView(pDocument1, nDoc1View0); + CPPUNIT_ASSERT_EQUAL(nDoc1View0, pDocument1->m_pDocumentClass->getView(pDocument1)); + CPPUNIT_ASSERT_EQUAL(nDocId1, SfxLokHelper::getDocumentIdOfView(nDoc1View1)); + pDocument1->m_pDocumentClass->destroyView(pDocument1, nDoc1View1); + CPPUNIT_ASSERT_EQUAL(1, pDocument1->m_pDocumentClass->getViewsCount(pDocument1)); + + // The views of document2 should be unchanged. + CPPUNIT_ASSERT(pDocument2->m_pDocumentClass->getViewIds(pDocument2, aViewIdsDoc2.data(), aViewIdsDoc2.size())); + CPPUNIT_ASSERT_EQUAL(nDoc2View0, aViewIdsDoc2[0]); + CPPUNIT_ASSERT_EQUAL(nDoc2View1, aViewIdsDoc2[1]); + // Switch views in the second doc. + CPPUNIT_ASSERT_EQUAL(nDocId2, SfxLokHelper::getDocumentIdOfView(nDoc2View0)); + pDocument2->m_pDocumentClass->setView(pDocument2, nDoc2View0); + CPPUNIT_ASSERT_EQUAL(nDoc2View0, pDocument2->m_pDocumentClass->getView(pDocument2)); + CPPUNIT_ASSERT_EQUAL(nDocId2, SfxLokHelper::getDocumentIdOfView(nDoc2View1)); + pDocument2->m_pDocumentClass->destroyView(pDocument2, nDoc2View1); + CPPUNIT_ASSERT_EQUAL(1, pDocument2->m_pDocumentClass->getViewsCount(pDocument2)); + + closeDoc(document2, xComponent2); + + closeDoc(document1, xComponent1); +} + void DesktopLOKTest::testControlState() { LibLODocument_Impl* pDocument = loadDoc("search.ods"); diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 6fe7347e9b70..9bcfff524bbf 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -1229,6 +1229,8 @@ LibLODocument_Impl::LibLODocument_Impl(const uno::Reference <css::lang::XCompone : mxComponent(xComponent) , mnDocumentId(nDocumentId) { + assert(nDocumentId != -1 && "Cannot set mnDocumentId to -1"); + m_pDocumentClass = gDocumentClass.lock(); if (!m_pDocumentClass) { @@ -2292,7 +2294,6 @@ static LibreOfficeKitDocument* lo_documentLoadWithOptions(LibreOfficeKit* pThis, LibLODocument_Impl* pDocument = new LibLODocument_Impl(xComponent, nDocumentIdCounter++); // After loading the document, its initial view is the "current" view. - SfxLokHelper::setDocumentIdOfView(pDocument->mnDocumentId); if (pLib->mpCallback) { int nState = doc_getSignatureState(pDocument); @@ -3358,13 +3359,13 @@ static void doc_registerCallback(LibreOfficeKitDocument* pThis, LibLODocument_Impl* pDocument = static_cast<LibLODocument_Impl*>(pThis); - int nView = SfxLokHelper::getView(); + const int nView = SfxLokHelper::getView(); if (nView < 0) return; + const size_t nId = nView; if (pCallback != nullptr) { - size_t nId = nView; for (auto& pair : pDocument->mpCallbackFlushHandlers) { if (pair.first == nId) @@ -3375,7 +3376,6 @@ static void doc_registerCallback(LibreOfficeKitDocument* pThis, } else { - size_t nId = nView; for (auto& pair : pDocument->mpCallbackFlushHandlers) { if (pair.first == nId) @@ -3389,7 +3389,6 @@ static void doc_registerCallback(LibreOfficeKitDocument* pThis, if (pCallback != nullptr) { - size_t nId = nView; for (const auto& pair : pDocument->mpCallbackFlushHandlers) { if (pair.first == nId) @@ -3397,11 +3396,19 @@ static void doc_registerCallback(LibreOfficeKitDocument* pThis, pDocument->mpCallbackFlushHandlers[nView]->addViewStates(pair.first); } - } - if (SfxViewShell* pViewShell = SfxViewShell::Current()) + if (SfxViewShell* pViewShell = SfxViewShell::Current()) + { + pViewShell->registerLibreOfficeKitViewCallback( + CallbackFlushHandler::callback, pDocument->mpCallbackFlushHandlers[nView].get()); + } + } + else { - pViewShell->registerLibreOfficeKitViewCallback(CallbackFlushHandler::callback, pDocument->mpCallbackFlushHandlers[nView].get()); + if (SfxViewShell* pViewShell = SfxViewShell::Current()) + { + pViewShell->registerLibreOfficeKitViewCallback(nullptr, nullptr); + } } } @@ -5145,7 +5152,8 @@ static int doc_createViewWithOptions(LibreOfficeKitDocument* pThis, const OUString aDeviceFormFactor = extractParameter(aOptions, "DeviceFormFactor"); SfxLokHelper::setDeviceFormFactor(aDeviceFormFactor); - int nId = SfxLokHelper::createView(); + LibLODocument_Impl* pDocument = static_cast<LibLODocument_Impl*>(pThis); + const int nId = SfxLokHelper::createView(pDocument->mnDocumentId); #ifdef IOS (void) pThis; @@ -5193,24 +5201,26 @@ static int doc_getView(SAL_UNUSED_PARAMETER LibreOfficeKitDocument* /*pThis*/) return SfxLokHelper::getView(); } -static int doc_getViewsCount(SAL_UNUSED_PARAMETER LibreOfficeKitDocument* /*pThis*/) +static int doc_getViewsCount(SAL_UNUSED_PARAMETER LibreOfficeKitDocument* pThis) { comphelper::ProfileZone aZone("doc_getViewsCount"); SolarMutexGuard aGuard; SetLastExceptionMsg(); - return SfxLokHelper::getViewsCount(); + LibLODocument_Impl* pDocument = static_cast<LibLODocument_Impl*>(pThis); + return SfxLokHelper::getViewsCount(pDocument->mnDocumentId); } -static bool doc_getViewIds(SAL_UNUSED_PARAMETER LibreOfficeKitDocument* /*pThis*/, int* pArray, size_t nSize) +static bool doc_getViewIds(SAL_UNUSED_PARAMETER LibreOfficeKitDocument* pThis, int* pArray, size_t nSize) { comphelper::ProfileZone aZone("doc_getViewsIds"); SolarMutexGuard aGuard; SetLastExceptionMsg(); - return SfxLokHelper::getViewIds(pArray, nSize); + LibLODocument_Impl* pDocument = static_cast<LibLODocument_Impl*>(pThis); + return SfxLokHelper::getViewIds(pDocument->mnDocumentId, pArray, nSize); } static void doc_setViewLanguage(SAL_UNUSED_PARAMETER LibreOfficeKitDocument* /*pThis*/, int nId, const char* language) diff --git a/include/editeng/outliner.hxx b/include/editeng/outliner.hxx index f06bd9a7448d..a6bc9fbd7ff2 100644 --- a/include/editeng/outliner.hxx +++ b/include/editeng/outliner.hxx @@ -365,7 +365,6 @@ class SAL_NO_VTABLE SAL_DLLPUBLIC_RTTI OutlinerViewShell public: virtual void libreOfficeKitViewCallback(int nType, const char* pPayload) const = 0; virtual ViewShellId GetViewShellId() const = 0; - virtual void SetDocId(ViewShellDocId nId) = 0; virtual ViewShellDocId GetDocId() const = 0; /// Wrapper around SfxLokHelper::notifyOtherViews(). virtual void NotifyOtherViews(int nType, const OString& rKey, const OString& rPayload) = 0; diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx index 2aad968681b8..521bf4207458 100644 --- a/include/sfx2/lokhelper.hxx +++ b/include/sfx2/lokhelper.hxx @@ -45,19 +45,21 @@ class SFX2_DLLPUBLIC SfxLokHelper { public: /// Create a new view shell from the current view frame. + /// This assumes a single document is ever loaded. static int createView(); + /// Create a new view shell for the given DocId, for multi-document support. + static int createView(int nDocId); /// Destroy a view shell from the global shell list. static void destroyView(int nId); /// Set a view shell as current one. static void setView(int nId); /// Get the currently active view. static int getView(const SfxViewShell* pViewShell = nullptr); - /// Get the number of views of the current object shell. - static std::size_t getViewsCount(); - /// Get viewIds of views of the current object shell. - static bool getViewIds(int* pArray, size_t nSize); - /// Set the document id of the currently active view - static void setDocumentIdOfView(int nId); + /// Get the number of views of the current DocId. + static std::size_t getViewsCount(int nDocId); + /// Get viewIds of views of the current DocId. + static bool getViewIds(int nDocId, int* pArray, size_t nSize); + /// Get the document id for a view static int getDocumentIdOfView(int nViewId); /// Get the default language that should be used for views @@ -125,6 +127,9 @@ public: /// A special value to signify 'infinity'. /// This value is chosen such that sal_Int32 will not overflow when manipulated. static const tools::Long MaxTwips = 1e9; + +private: + static int createView(SfxViewFrame* pViewFrame, ViewShellDocId docId); }; template<typename ViewShellType, typename FunctionType> diff --git a/include/sfx2/viewsh.hxx b/include/sfx2/viewsh.hxx index 7965cb79dfc4..67671a6a678b 100644 --- a/include/sfx2/viewsh.hxx +++ b/include/sfx2/viewsh.hxx @@ -165,6 +165,9 @@ friend class SfxPrinterController; LanguageTag maLOKLocale; LOKDeviceFormFactor maLOKDeviceFormFactor; + /// Used to set the DocId at construction time. See SetCurrentDocId. + static ViewShellDocId mnCurrentDocId; + protected: virtual void Activate(bool IsMDIActivate) override; virtual void Deactivate(bool IsMDIActivate) override; @@ -339,8 +342,18 @@ public: virtual void dumpAsXml(xmlTextWriterPtr pWriter) const; /// See OutlinerViewShell::GetViewShellId(). ViewShellId GetViewShellId() const override; - void SetDocId(ViewShellDocId nId) override; + + /// Set the current DocId, which is used by Mobile LOKit to + /// load multiple documents and yet identify the views of each. + /// There are events that are fired while creating a new view, + /// and if we don't have a DocId, we can't know which other views + /// within the same document (if any) should get those events. + /// By setting this static value, we are able to set the DocId + /// of each SfxViewShell at construction time. + static void SetCurrentDocId(ViewShellDocId nId); + /// Get the DocId used by Mobile LOKit to load multiple documents. ViewShellDocId GetDocId() const override; + /// See OutlinerViewShell::NotifyOtherViews(). void NotifyOtherViews(int nType, const OString& rKey, const OString& rPayload) override; /// See OutlinerViewShell::NotifyOtherView(). diff --git a/sc/source/ui/view/tabvwshc.cxx b/sc/source/ui/view/tabvwshc.cxx index f208a07af7af..6cafc717b992 100644 --- a/sc/source/ui/view/tabvwshc.cxx +++ b/sc/source/ui/view/tabvwshc.cxx @@ -520,7 +520,8 @@ void ScTabViewShell::notifyAllViewsHeaderInvalidation(const SfxViewShell* pForVi while (pViewShell) { ScTabViewShell* pTabViewShell = dynamic_cast<ScTabViewShell*>(pViewShell); - if (pTabViewShell && pViewShell->GetDocId() == pForViewShell->GetDocId() && (nCurrentTabIndex == -1 || pTabViewShell->getPart() == nCurrentTabIndex)) + if (pTabViewShell && pViewShell->GetDocId() == pForViewShell->GetDocId() + && (nCurrentTabIndex == -1 || pTabViewShell->getPart() == nCurrentTabIndex)) { pViewShell->libreOfficeKitViewCallback(LOK_CALLBACK_INVALIDATE_HEADER, aPayload.getStr()); } diff --git a/sd/qa/unit/tiledrendering/LOKitSearchTest.cxx b/sd/qa/unit/tiledrendering/LOKitSearchTest.cxx index a34914b88a60..beba53b67078 100644 --- a/sd/qa/unit/tiledrendering/LOKitSearchTest.cxx +++ b/sd/qa/unit/tiledrendering/LOKitSearchTest.cxx @@ -23,6 +23,7 @@ #include <comphelper/string.hxx> #include <comphelper/lok.hxx> #include <sfx2/dispatch.hxx> +#include <sfx2/lokhelper.hxx> #include <sfx2/viewfrm.hxx> #include <svl/srchitem.hxx> #include <svl/stritem.hxx> diff --git a/sd/source/ui/unoidl/unomodel.cxx b/sd/source/ui/unoidl/unomodel.cxx index 267fdbb3c34e..2ffc5acc0664 100644 --- a/sd/source/ui/unoidl/unomodel.cxx +++ b/sd/source/ui/unoidl/unomodel.cxx @@ -2305,6 +2305,9 @@ int SdXImpressDocument::getParts() { // TODO: master pages? // Read: drviews1.cxx + if (!mpDoc) + return 0; + return mpDoc->GetSdPageCount(PageKind::Standard); } diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx index 1240209d9fb2..f86b69a8af29 100644 --- a/sfx2/source/view/lokhelper.cxx +++ b/sfx2/source/view/lokhelper.cxx @@ -56,7 +56,10 @@ public: --m_nDisabled; } - static bool disabled() { return m_nDisabled != 0; } + static inline bool disabled() + { + return !comphelper::LibreOfficeKit::isActive() || m_nDisabled != 0; + } private: static int m_nDisabled; @@ -71,28 +74,57 @@ LanguageTag g_defaultLanguageTag("en-US", true); LOKDeviceFormFactor g_deviceFormFactor = LOKDeviceFormFactor::UNKNOWN; } -int SfxLokHelper::createView() +int SfxLokHelper::createView(SfxViewFrame* pViewFrame, ViewShellDocId docId) { - SfxViewFrame* pViewFrame = SfxViewFrame::GetFirst(); + assert(docId >= ViewShellDocId(0) && "Cannot createView for invalid (negative) DocId."); + if (pViewFrame == nullptr) return -1; - SfxViewShell* pPrevViewShell = SfxViewShell::Current(); - ViewShellDocId nId; - if (pPrevViewShell) - nId = pPrevViewShell->GetDocId(); + + SfxViewShell::SetCurrentDocId(docId); SfxRequest aRequest(pViewFrame, SID_NEWWINDOW); pViewFrame->ExecView_Impl(aRequest); SfxViewShell* pViewShell = SfxViewShell::Current(); if (pViewShell == nullptr) return -1; - if (pPrevViewShell) - pViewShell->SetDocId(nId); + + assert(pViewShell->GetDocId() == docId && "DocId must be already set!"); return static_cast<sal_Int32>(pViewShell->GetViewShellId()); } +int SfxLokHelper::createView() +{ + // Assumes a single document, or at least that the + // current view belongs to the document on which the + // view will be created. + SfxViewShell* pViewShell = SfxViewShell::Current(); + if (pViewShell == nullptr) + return -1; + + return createView(pViewShell->GetViewFrame(), pViewShell->GetDocId()); +} + +int SfxLokHelper::createView(int nDocId) +{ + const SfxApplication* pApp = SfxApplication::Get(); + if (pApp == nullptr) + return -1; + + // Find a shell with the given DocId. + const ViewShellDocId docId(nDocId); + for (const SfxViewShell* pViewShell : pApp->GetViewShells_Impl()) + { + if (pViewShell->GetDocId() == docId) + return createView(pViewShell->GetViewFrame(), docId); + } + + // No frame with nDocId found. + return -1; +} + void SfxLokHelper::destroyView(int nId) { - SfxApplication* pApp = SfxApplication::Get(); + const SfxApplication* pApp = SfxApplication::Get(); if (pApp == nullptr) return; @@ -157,14 +189,15 @@ int SfxLokHelper::getView(const SfxViewShell* pViewShell) return static_cast<sal_Int32>(pViewShell->GetViewShellId()); } -std::size_t SfxLokHelper::getViewsCount() +std::size_t SfxLokHelper::getViewsCount(int nDocId) { + assert(nDocId != -1 && "Cannot getViewsCount for invalid DocId -1"); + SfxApplication* pApp = SfxApplication::Get(); if (!pApp) return 0; - const SfxViewShell* const pCurrentViewShell = SfxViewShell::Current(); - const ViewShellDocId nCurrentDocId = pCurrentViewShell ? pCurrentViewShell->GetDocId() : ViewShellDocId(-1); + const ViewShellDocId nCurrentDocId(nDocId); std::size_t n = 0; SfxViewShell* pViewShell = SfxViewShell::GetFirst(); while (pViewShell) @@ -173,40 +206,36 @@ std::size_t SfxLokHelper::getViewsCount() n++; pViewShell = SfxViewShell::GetNext(*pViewShell); } + return n; } -bool SfxLokHelper::getViewIds(int* pArray, size_t nSize) +bool SfxLokHelper::getViewIds(int nDocId, int* pArray, size_t nSize) { + assert(nDocId != -1 && "Cannot getViewsIds for invalid DocId -1"); + SfxApplication* pApp = SfxApplication::Get(); if (!pApp) return false; - const SfxViewShell* const pCurrentViewShell = SfxViewShell::Current(); - const ViewShellDocId nCurrentDocId = pCurrentViewShell ? pCurrentViewShell->GetDocId() : ViewShellDocId(-1); + const ViewShellDocId nCurrentDocId(nDocId); std::size_t n = 0; SfxViewShell* pViewShell = SfxViewShell::GetFirst(); while (pViewShell) { - if (n == nSize) - return false; if (pViewShell->GetDocId() == nCurrentDocId) { + if (n == nSize) + return false; + pArray[n] = static_cast<sal_Int32>(pViewShell->GetViewShellId()); n++; } + pViewShell = SfxViewShell::GetNext(*pViewShell); } - return true; -} -void SfxLokHelper::setDocumentIdOfView(int nId) -{ - SfxViewShell* pViewShell = SfxViewShell::Current(); - assert(pViewShell); - if (!pViewShell) - return; - pViewShell->SetDocId(ViewShellDocId(nId)); + return true; } int SfxLokHelper::getDocumentIdOfView(int nViewId) @@ -336,14 +365,25 @@ void SfxLokHelper::notifyOtherView(const SfxViewShell* pThisView, SfxViewShell c void SfxLokHelper::notifyOtherViews(const SfxViewShell* pThisView, int nType, const OString& rKey, const OString& rPayload) { + assert(pThisView != nullptr && "pThisView must be valid"); if (DisableCallbacks::disabled()) return; + // Cache the payload so we only have to generate it once, at most. + OString aPayload; + + const ViewShellDocId nCurrentDocId = pThisView->GetDocId(); SfxViewShell* pViewShell = SfxViewShell::GetFirst(); while (pViewShell) { - if (pViewShell != pThisView && pViewShell->GetDocId() == pThisView-> GetDocId()) - notifyOtherView(pThisView, pViewShell, nType, rKey, rPayload); + if (pViewShell != pThisView && nCurrentDocId == pViewShell->GetDocId()) + { + // Payload is only dependent on pThisView. + if (aPayload.isEmpty()) + aPayload = lcl_generateJSON(pThisView, rKey, rPayload); + + pViewShell->libreOfficeKitViewCallback(nType, aPayload.getStr()); + } pViewShell = SfxViewShell::GetNext(*pViewShell); } @@ -352,17 +392,25 @@ void SfxLokHelper::notifyOtherViews(const SfxViewShell* pThisView, int nType, co void SfxLokHelper::notifyOtherViews(const SfxViewShell* pThisView, int nType, const boost::property_tree::ptree& rTree) { - if (SfxLokHelper::getViewsCount() <= 1 || DisableCallbacks::disabled()) + assert(pThisView != nullptr && "pThisView must be valid"); + if (DisableCallbacks::disabled()) return; - // Payload is only dependent on pThisView. - OString aPayload = lcl_generateJSON(pThisView, rTree); + // Cache the payload so we only have to generate it once, at most. + OString aPayload; + const ViewShellDocId nCurrentDocId = pThisView->GetDocId(); SfxViewShell* pViewShell = SfxViewShell::GetFirst(); while (pViewShell) { - if (pViewShell != pThisView) + if (pViewShell != pThisView && nCurrentDocId == pViewShell->GetDocId()) + { + // Payload is only dependent on pThisView. + if (aPayload.isEmpty()) + aPayload = lcl_generateJSON(pThisView, rTree); + pViewShell->libreOfficeKitViewCallback(nType, aPayload.getStr()); + } pViewShell = SfxViewShell::GetNext(*pViewShell); } @@ -414,7 +462,7 @@ void SfxLokHelper::notifyWindow(const SfxViewShell* pThisView, { assert(pThisView != nullptr && "pThisView must be valid"); - if (SfxLokHelper::getViewsCount() <= 0 || nLOKWindowId == 0 || DisableCallbacks::disabled()) + if (nLOKWindowId == 0 || DisableCallbacks::disabled()) return; OStringBuffer aPayload; @@ -453,7 +501,7 @@ void SfxLokHelper::notifyInvalidation(SfxViewShell const* pThisView, const OStri void SfxLokHelper::notifyDocumentSizeChanged(SfxViewShell const* pThisView, const OString& rPayload, vcl::ITiledRenderable* pDoc, bool bInvalidateAll) { - if (!pDoc || pDoc->isDisposed() || !comphelper::LibreOfficeKit::isActive() || DisableCallbacks::disabled()) + if (!pDoc || pDoc->isDisposed() || DisableCallbacks::disabled()) return; if (bInvalidateAll) @@ -470,7 +518,7 @@ void SfxLokHelper::notifyDocumentSizeChanged(SfxViewShell const* pThisView, cons void SfxLokHelper::notifyDocumentSizeChangedAllViews(vcl::ITiledRenderable* pDoc, bool bInvalidateAll) { - if (!comphelper::LibreOfficeKit::isActive() || DisableCallbacks::disabled()) + if (DisableCallbacks::disabled()) return; // FIXME: Do we know whether it is the views for the document that is in the "current" view that has changed? diff --git a/sfx2/source/view/viewimp.hxx b/sfx2/source/view/viewimp.hxx index c1ee641fdc16..d61f86b5dd82 100644 --- a/sfx2/source/view/viewimp.hxx +++ b/sfx2/source/view/viewimp.hxx @@ -54,9 +54,9 @@ struct SfxViewShell_Impl bool m_bTiledSearching; static sal_uInt32 m_nLastViewShellId; const ViewShellId m_nViewShellId; - ViewShellDocId m_nDocId; + const ViewShellDocId m_nDocId; - explicit SfxViewShell_Impl(SfxViewShellFlags const nFlags); + explicit SfxViewShell_Impl(SfxViewShellFlags const nFlags, ViewShellDocId nDocId); ~SfxViewShell_Impl(); std::vector< SfxInPlaceClient* >* GetIPClients_Impl(bool bCreate = true) const; diff --git a/sfx2/source/view/viewsh.cxx b/sfx2/source/view/viewsh.cxx index f419e4f95c10..d35253d1342a 100644 --- a/sfx2/source/view/viewsh.cxx +++ b/sfx2/source/view/viewsh.cxx @@ -217,7 +217,7 @@ void SAL_CALL SfxClipboardChangeListener::changedContents( const datatransfer::c sal_uInt32 SfxViewShell_Impl::m_nLastViewShellId = 0; -SfxViewShell_Impl::SfxViewShell_Impl(SfxViewShellFlags const nFlags) +SfxViewShell_Impl::SfxViewShell_Impl(SfxViewShellFlags const nFlags, ViewShellDocId nDocId) : aInterceptorContainer( aMutex ) , m_bHasPrintOptions(nFlags & SfxViewShellFlags::HAS_PRINTOPTIONS) , m_nFamily(0xFFFF) // undefined, default set by TemplateDialog @@ -225,7 +225,7 @@ SfxViewShell_Impl::SfxViewShell_Impl(SfxViewShellFlags const nFlags) , m_pLibreOfficeKitViewData(nullptr) , m_bTiledSearching(false) , m_nViewShellId(SfxViewShell_Impl::m_nLastViewShellId++) -, m_nDocId(-1) +, m_nDocId(nDocId) { } @@ -1058,6 +1058,7 @@ void SfxViewShell::SetWindow //SfxGetpApp()->GrabFocus( pWindow ); } +ViewShellDocId SfxViewShell::mnCurrentDocId(0); SfxViewShell::SfxViewShell ( @@ -1067,7 +1068,7 @@ SfxViewShell::SfxViewShell ) : SfxShell(this) -, pImpl( new SfxViewShell_Impl(nFlags) ) +, pImpl( new SfxViewShell_Impl(nFlags, SfxViewShell::mnCurrentDocId) ) , pFrame(pViewFrame) , pWindow(nullptr) , bNoNewWindow( nFlags & SfxViewShellFlags::NO_NEWWINDOW ) @@ -1542,14 +1543,14 @@ ViewShellId SfxViewShell::GetViewShellId() const return pImpl->m_nViewShellId; } -void SfxViewShell::SetDocId(ViewShellDocId nId) +void SfxViewShell::SetCurrentDocId(ViewShellDocId nId) { - assert(static_cast<int>(pImpl->m_nDocId) == -1); - pImpl->m_nDocId = nId; + mnCurrentDocId = nId; } ViewShellDocId SfxViewShell::GetDocId() const { + assert(pImpl->m_nDocId >= ViewShellDocId(0) && "m_nDocId should have been initialized, but it is invalid."); return pImpl->m_nDocId; } diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx index 7b497ae8c600..dc57ef1e451a 100644 --- a/sw/qa/extras/tiledrendering/tiledrendering.cxx +++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx @@ -1124,7 +1124,7 @@ void SwTiledRenderingTest::testViewCursorCleanup() // Now destroy the second view. SfxLokHelper::destroyView(nView2); Scheduler::ProcessEventsToIdle(); - CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), SfxLokHelper::getViewsCount()); + CPPUNIT_ASSERT_EQUAL(static_cast<std::size_t>(1), SfxLokHelper::getViewsCount(0)); // Make sure that the graphic view selection on the first view is cleaned up. CPPUNIT_ASSERT(!aView1.m_bGraphicViewSelection); } |