summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--desktop/inc/lib/init.hxx3
-rw-r--r--desktop/qa/desktop_lib/test_desktop_lib.cxx100
-rw-r--r--desktop/source/lib/init.cxx36
-rw-r--r--include/editeng/outliner.hxx1
-rw-r--r--include/sfx2/lokhelper.hxx17
-rw-r--r--include/sfx2/viewsh.hxx15
-rw-r--r--sc/source/ui/view/tabvwshc.cxx3
-rw-r--r--sd/qa/unit/tiledrendering/LOKitSearchTest.cxx1
-rw-r--r--sd/source/ui/unoidl/unomodel.cxx3
-rw-r--r--sfx2/source/view/lokhelper.cxx123
-rw-r--r--sfx2/source/view/viewimp.hxx4
-rw-r--r--sfx2/source/view/viewsh.cxx13
-rw-r--r--sw/qa/extras/tiledrendering/tiledrendering.cxx2
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);
}