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 | 123 | ||||
-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, 250 insertions, 71 deletions
diff --git a/desktop/inc/lib/init.hxx b/desktop/inc/lib/init.hxx index 237a17a59eee..1a927280e24b 100644 --- a/desktop/inc/lib/init.hxx +++ b/desktop/inc/lib/init.hxx @@ -151,7 +151,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 7acb50499ae9..f448965c02d7 100644 --- a/desktop/qa/desktop_lib/test_desktop_lib.cxx +++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx @@ -225,6 +225,7 @@ public: void testCalcSaveAs(); void testControlState(); void testMetricField(); + void testMultiDocuments(); void testABI(); CPPUNIT_TEST_SUITE(DesktopLOKTest); @@ -287,6 +288,7 @@ public: CPPUNIT_TEST(testCalcSaveAs); CPPUNIT_TEST(testControlState); CPPUNIT_TEST(testMetricField); + CPPUNIT_TEST(testMultiDocuments); CPPUNIT_TEST(testABI); CPPUNIT_TEST_SUITE_END(); @@ -352,10 +354,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); } @@ -2987,6 +2992,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); +} + namespace { constexpr size_t classOffset(int i) diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index fdd92d2d3430..08a4247513c7 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -1241,6 +1241,8 @@ LibLODocument_Impl::LibLODocument_Impl(const uno::Reference <css::lang::XCompone : mxComponent(xComponent) , mnDocumentId(nDocumentId) { + assert(nDocumentId != -1 && "Cannot set mnDocumentId to -1"); + if (!(m_pDocumentClass = gDocumentClass.lock())) { m_pDocumentClass.reset(new LibreOfficeKitDocumentClass); @@ -2289,7 +2291,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); @@ -3350,13 +3351,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) @@ -3367,7 +3368,6 @@ static void doc_registerCallback(LibreOfficeKitDocument* pThis, } else { - size_t nId = nView; for (auto& pair : pDocument->mpCallbackFlushHandlers) { if (pair.first == nId) @@ -3381,7 +3381,6 @@ static void doc_registerCallback(LibreOfficeKitDocument* pThis, if (pCallback != nullptr) { - size_t nId = nView; for (const auto& pair : pDocument->mpCallbackFlushHandlers) { if (pair.first == nId) @@ -3389,11 +3388,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); + } } } @@ -5146,7 +5153,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; @@ -5194,24 +5202,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 70dd8fd3b2fc..c77c2f246ad1 100644 --- a/include/editeng/outliner.hxx +++ b/include/editeng/outliner.hxx @@ -363,7 +363,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 e3c75b4191c3..3e37b8b68597 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 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 e9964a20adfb..e9863fd99a03 100644 --- a/include/sfx2/viewsh.hxx +++ b/include/sfx2/viewsh.hxx @@ -161,6 +161,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; @@ -340,8 +343,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 3a22fee7e924..8c7df132e203 100644 --- a/sc/source/ui/view/tabvwshc.cxx +++ b/sc/source/ui/view/tabvwshc.cxx @@ -521,7 +521,8 @@ void ScTabViewShell::notifyAllViewsHeaderInvalidation(SfxViewShell* pForViewShel 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 ac2695441575..fa5a875573fb 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 cea0b9f4c420..f02868f0ca83 100644 --- a/sd/source/ui/unoidl/unomodel.cxx +++ b/sd/source/ui/unoidl/unomodel.cxx @@ -2296,6 +2296,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 864523e50fd6..4928dd3102e9 100644 --- a/sfx2/source/view/lokhelper.cxx +++ b/sfx2/source/view/lokhelper.cxx @@ -55,7 +55,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; @@ -70,28 +73,57 @@ static LanguageTag g_defaultLanguageTag("en-US", true); static 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; @@ -156,56 +188,52 @@ 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) { - if (pViewShell->GetDocId() == nCurrentDocId) - n++; + n += (pViewShell->GetDocId() == nCurrentDocId); 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) @@ -335,14 +363,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 && (pThisView->GetDocId() == ViewShellDocId(-1) || 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); } @@ -351,17 +390,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); } @@ -415,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; @@ -454,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) @@ -471,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 d89a49c79154..d2c39965a225 100644 --- a/sfx2/source/view/viewimp.hxx +++ b/sfx2/source/view/viewimp.hxx @@ -58,9 +58,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 b9abc8833573..14cbd2c10a08 100644 --- a/sfx2/source/view/viewsh.cxx +++ b/sfx2/source/view/viewsh.cxx @@ -231,7 +231,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 @@ -239,7 +239,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) { } @@ -1069,6 +1069,7 @@ void SfxViewShell::SetWindow //SfxGetpApp()->GrabFocus( pWindow ); } +ViewShellDocId SfxViewShell::mnCurrentDocId(0); SfxViewShell::SfxViewShell ( @@ -1078,7 +1079,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 ) @@ -1553,14 +1554,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 4b4f00887a74..320ee898a2ed 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); } |