comphelper/source/misc/lok.cxx | 13 +++++++++++++ desktop/qa/desktop_lib/test_desktop_lib.cxx | 2 +- desktop/source/lib/init.cxx | 4 +++- include/comphelper/lok.hxx | 13 +++++++++++++ include/sfx2/viewsh.hxx | 11 ----------- include/svl/undo.hxx | 2 +- sfx2/source/view/lokhelper.cxx | 2 +- sfx2/source/view/viewsh.cxx | 9 +-------- vcl/source/app/svapp.cxx | 10 ++++++++++ 9 files changed, 43 insertions(+), 23 deletions(-)
New commits: commit 7b8a8efedf9996404b9e578b215c85a0a5f3c722 Author: Caolán McNamara <[email protected]> AuthorDate: Tue Nov 11 13:46:56 2025 +0000 Commit: Caolán McNamara <[email protected]> CommitDate: Tue Nov 11 20:33:13 2025 +0100 save/restore docId in Application::Reschedule similar to what we do for viewID. On attemting to load multiple documents StatusIndicator::start calls Application::Reschedule during load of document #1. That inner loop ends up loading document #2. The inner loop ends, and load of document #1 completes in the outer loop. Unfortunately the inner loop left the current DocumentId as that of the inner document #2, so the document id set on the view of #1 is incorrect. Extend the similar fix for viewId switching during Reschedule to restore the docId. If this Reschedule happens at any other time except load then restoring the viewId is sufficient to identify the correct document, but in the load case there is no viewId yet Move the mnCurrentDocId out of sfx2 and ViewShell into comphelper so it's available from vcl without needing to make any adjustments to LibreOfficeKit.h[xx] Change-Id: Ied70e0f9ff33f2587cfbcb02b0c9ca3cd4792cfd Reviewed-on: https://gerrit.libreoffice.org/c/core/+/193807 Reviewed-by: Miklos Vajna <[email protected]> Tested-by: Jenkins CollaboraOffice <[email protected]> diff --git a/comphelper/source/misc/lok.cxx b/comphelper/source/misc/lok.cxx index 4dc3afaf01d5..189a01aad621 100644 --- a/comphelper/source/misc/lok.cxx +++ b/comphelper/source/misc/lok.cxx @@ -44,6 +44,9 @@ static bool g_bSlideshowRendering(false); static Compat g_eCompatFlags(Compat::none); +/// Used to set the DocId at ViewShell construction time. +static ViewShellDocId g_nCurrentDocId; + static std::function<bool(void*, int)> g_pAnyInputCallback; static void* g_pAnyInputCallbackData; static std::function<int()> g_pMostUrgentPriorityGetter; @@ -400,6 +403,16 @@ int getView() return g_pViewGetter(); } +ViewShellDocId getDocId() +{ + return g_nCurrentDocId; +} + +void setDocId(ViewShellDocId nDocId) +{ + g_nCurrentDocId = nDocId; +} + void setInitialClientVisibleArea(const awt::Rectangle& rClientVisibleArea) { g_aInitialClientVisibleArea = rClientVisibleArea; diff --git a/desktop/qa/desktop_lib/test_desktop_lib.cxx b/desktop/qa/desktop_lib/test_desktop_lib.cxx index df6976bbf21a..0186e9ba9e4e 100644 --- a/desktop/qa/desktop_lib/test_desktop_lib.cxx +++ b/desktop/qa/desktop_lib/test_desktop_lib.cxx @@ -380,7 +380,7 @@ DesktopLOKTest::loadDocUrlImpl(const OUString& rFileURL, LibreOfficeKitDocumentT } static int nDocumentIdCounter = 0; - SfxViewShell::SetCurrentDocId(ViewShellDocId(nDocumentIdCounter)); + comphelper::LibreOfficeKit::setDocId(ViewShellDocId(nDocumentIdCounter)); mxComponent = loadFromDesktop(rFileURL, aService); std::unique_ptr<LibLODocument_Impl> pDocument(new LibLODocument_Impl(mxComponent, nDocumentIdCounter)); diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index 3320d08140fd..160b8451d3f9 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -2997,7 +2997,7 @@ static LibreOfficeKitDocument* lo_documentLoadWithOptions(LibreOfficeKit* pThis, HostFilter::setExemptVerifyHost(OUString(pExemptVerifyHost, strlen(pExemptVerifyHost), RTL_TEXTENCODING_UTF8)); const int nThisDocumentId = nDocumentIdCounter++; - SfxViewShell::SetCurrentDocId(ViewShellDocId(nThisDocumentId)); + comphelper::LibreOfficeKit::setDocId(ViewShellDocId(nThisDocumentId)); uno::Reference<lang::XComponent> xComponent = xComponentLoader->loadComponentFromURL( aURL, u"_blank"_ustr, 0, aFilterOptions); @@ -3011,6 +3011,8 @@ static LibreOfficeKitDocument* lo_documentLoadWithOptions(LibreOfficeKit* pThis, return nullptr; } + assert(comphelper::LibreOfficeKit::getDocId() == ViewShellDocId(nThisDocumentId) && "incorrect docid set on document"); + LibLODocument_Impl* pDocument = new LibLODocument_Impl(xComponent, nThisDocumentId); // After loading the document, its initial view is the "current" view. diff --git a/include/comphelper/lok.hxx b/include/comphelper/lok.hxx index 2945d16186e4..9a992f6901cd 100644 --- a/include/comphelper/lok.hxx +++ b/include/comphelper/lok.hxx @@ -13,8 +13,11 @@ #include <functional> #include <comphelper/comphelperdllapi.h> +#include <o3tl/strong_int.hxx> #include <rtl/ustring.hxx> +typedef o3tl::strong_int<int, struct ViewShellDocIdTag> ViewShellDocId; + class LanguageTag; namespace com::sun::star::awt { @@ -154,6 +157,16 @@ COMPHELPER_DLLPUBLIC void setView(int nView); COMPHELPER_DLLPUBLIC void setViewGetter(std::function<int()> pViewGetter); COMPHELPER_DLLPUBLIC int getView(); +/// 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. +COMPHELPER_DLLPUBLIC void setDocId(ViewShellDocId nDocId); +COMPHELPER_DLLPUBLIC ViewShellDocId getDocId(); + COMPHELPER_DLLPUBLIC void setInitialClientVisibleArea(const css::awt::Rectangle& rClientVisibleArea); COMPHELPER_DLLPUBLIC css::awt::Rectangle getInitialClientVisibleArea(); diff --git a/include/sfx2/viewsh.hxx b/include/sfx2/viewsh.hxx index a4815690ad62..90e87bf9d006 100644 --- a/include/sfx2/viewsh.hxx +++ b/include/sfx2/viewsh.hxx @@ -184,9 +184,6 @@ friend class SfxPrinterController; bool maLOKIsTimezoneSet; bool mbLOKColorPreviewEnabled; - /// Used to set the DocId at construction time. See SetCurrentDocId. - static ViewShellDocId mnCurrentDocId; - /// Used for async export std::shared_ptr<SfxStoringHelper> m_xHelper; @@ -425,14 +422,6 @@ public: /// See OutlinerViewShell::GetViewShellId(). ViewShellId GetViewShellId() const 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; diff --git a/include/svl/undo.hxx b/include/svl/undo.hxx index 2ca0f3b0f8a4..0fd673f0f337 100644 --- a/include/svl/undo.hxx +++ b/include/svl/undo.hxx @@ -20,6 +20,7 @@ #define INCLUDED_SVL_UNDO_HXX #include <svl/svldllapi.h> +#include <comphelper/lok.hxx> #include <rtl/ustring.hxx> #include <tools/datetime.hxx> #include <o3tl/strong_int.hxx> @@ -29,7 +30,6 @@ #include <vector> typedef o3tl::strong_int<sal_Int32, struct ViewShellIdTag> ViewShellId; -typedef o3tl::strong_int<int, struct ViewShellDocIdTag> ViewShellDocId; typedef struct _xmlTextWriter* xmlTextWriterPtr; diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx index 5466d2a0fd20..9348d7fe2856 100644 --- a/sfx2/source/view/lokhelper.cxx +++ b/sfx2/source/view/lokhelper.cxx @@ -125,7 +125,7 @@ int SfxLokHelper::createView(SfxViewFrame& rViewFrame, ViewShellDocId docId) // something has likely cleared the original SID_INTERACTIONHANDLER assert(!isSfxMediumMissingInteractionHandled(rViewFrame) && "original XInteractionHandler missing"); - SfxViewShell::SetCurrentDocId(docId); + comphelper::LibreOfficeKit::setDocId(docId); SfxRequest aRequest(rViewFrame, SID_NEWWINDOW); rViewFrame.ExecView_Impl(aRequest); SfxViewShell* pViewShell = SfxViewShell::Current(); diff --git a/sfx2/source/view/viewsh.cxx b/sfx2/source/view/viewsh.cxx index 23004089e82b..a1bd1b37b714 100644 --- a/sfx2/source/view/viewsh.cxx +++ b/sfx2/source/view/viewsh.cxx @@ -2725,8 +2725,6 @@ void SfxViewShell::SetWindow //SfxGetpApp()->GrabFocus( pWindow ); } -ViewShellDocId SfxViewShell::mnCurrentDocId(0); - SfxViewShell::SfxViewShell ( SfxViewFrame& rViewFrame, /* <SfxViewFrame>, which will be @@ -2735,7 +2733,7 @@ SfxViewShell::SfxViewShell ) : SfxShell(this) -, pImpl( new SfxViewShell_Impl(nFlags, SfxViewShell::mnCurrentDocId) ) +, pImpl( new SfxViewShell_Impl(nFlags, comphelper::LibreOfficeKit::getDocId()) ) , rFrame(rViewFrame) , pWindow(nullptr) , bNoNewWindow( nFlags & SfxViewShellFlags::NO_NEWWINDOW ) @@ -3544,11 +3542,6 @@ ViewShellId SfxViewShell::GetViewShellId() const return pImpl->m_nViewShellId; } -void SfxViewShell::SetCurrentDocId(ViewShellDocId nId) -{ - mnCurrentDocId = nId; -} - ViewShellDocId SfxViewShell::GetDocId() const { assert(pImpl->m_nDocId >= ViewShellDocId(0) && "m_nDocId should have been initialized, but it is invalid."); diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx index c97f7fadeb43..dd11e4912a4c 100644 --- a/vcl/source/app/svapp.cxx +++ b/vcl/source/app/svapp.cxx @@ -406,13 +406,23 @@ bool Application::Reschedule( bool i_bAllEvents ) return false; } int nOldView = -1; + ViewShellDocId nOldDocId(-1); if (comphelper::LibreOfficeKit::isActive()) { nOldView = comphelper::LibreOfficeKit::getView(); + nOldDocId = comphelper::LibreOfficeKit::getDocId(); } bool bRet = ImplYield(false, i_bAllEvents); if (comphelper::LibreOfficeKit::isActive()) { + // Yield may have changed the current docId, restore the old value, + // (which is cheap). If there is a view to restore this doesn't matter + // much, but if there isn't yet, as in the case of loading a new + // document, then this ensures that the next view to be created is + // created with the expected document id. + assert(nOldDocId.get() != -1 && "won't be unset"); + comphelper::LibreOfficeKit::setDocId(nOldDocId); + int nNewView = comphelper::LibreOfficeKit::getView(); if (nOldView != -1 && nNewView != -1 && nOldView != nNewView) {
