comphelper/source/misc/lok.cxx | 33 ++++++++++++++++++++++++ desktop/source/lib/init.cxx | 1 include/comphelper/lok.hxx | 7 +++++ include/sfx2/lokhelper.hxx | 2 + sfx2/source/view/lokhelper.cxx | 10 +++++++ sw/qa/extras/tiledrendering/tiledrendering2.cxx | 1 vcl/source/app/svapp.cxx | 17 +++++++++++- 7 files changed, 70 insertions(+), 1 deletion(-)
New commits: commit 1e06592574472cea476cf2d505d53c7838004fc0 Author: Miklos Vajna <[email protected]> AuthorDate: Thu Jan 2 16:18:03 2025 +0100 Commit: Miklos Vajna <[email protected]> CommitDate: Thu Jan 9 11:55:02 2025 +0100 cool#10782 vcl lok: avoid changing the current view during Yield Commit 520cc546e2940bdfbc45eab1e569bb06bab17a9c (cool#10782 sfx2 lok: fix bad view id on PDF export, 2024-12-20) provided a specific fix for one case where spinning the main loop can result in callbacks being emitted on the wrong view. Hunting down all the SfxViewShell::Current() calls and auditing them if they are problematic in practice is a large task, so it's desirable to handle this problem in a more generic way. Fix the problem by pushing/popping the current LOK view in Application::Reschedule(), which is what e.g. the framework/ status bar code uses during PDF export. This keeps the original problem fixed but is more generic. This requires storing function pointers in comphelper/, since normally vcl/ code can't call SfxLokHelper, since sfx2/ already depends on vcl/. The fix can be tested by reverting the original fix: git show 520cc546e2940bdfbc45eab1e569bb06bab17a9c -- sfx2|git apply -R and then running the testcase: make -C sw -sr CppunitTest_sw_tiledrendering CPPUNIT_TEST_NAME=testPDFExportViewSwitch which now passes even if the sfx2-level fix is not there. Keep that specific fix, though: the less time we assume SfxViewShell::Current() returns the correct view, the better. Change-Id: Ic1811ff1e67f73fa5066af775d31589136b8502a Reviewed-on: https://gerrit.libreoffice.org/c/core/+/179993 Tested-by: Jenkins Reviewed-by: Miklos Vajna <[email protected]> diff --git a/comphelper/source/misc/lok.cxx b/comphelper/source/misc/lok.cxx index 88521ebb455e..cd1333711e4d 100644 --- a/comphelper/source/misc/lok.cxx +++ b/comphelper/source/misc/lok.cxx @@ -40,6 +40,9 @@ static Compat g_eCompatFlags(Compat::none); static std::function<bool(void*)> g_pAnyInputCallback; static void* g_pAnyInputCallbackData; +static std::function<void(int)> g_pViewSetter; +static std::function<int()> g_pViewGetter; + namespace { @@ -337,6 +340,36 @@ bool anyInput() return bRet; } +void setViewSetter(std::function<void(int)> pViewSetter) +{ + g_pViewSetter = pViewSetter; +} + +void setView(int nView) +{ + if (!g_pViewSetter) + { + return; + } + + g_pViewSetter(nView); +} + +void setViewGetter(std::function<int()> pViewGetter) +{ + g_pViewGetter = pViewGetter; +} + +int getView() +{ + if (!g_pViewGetter) + { + return -1; + } + + return g_pViewGetter(); +} + } // namespace /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/desktop/source/lib/init.cxx b/desktop/source/lib/init.cxx index dc0f4fdd5e89..6a6cffd57e95 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -7794,6 +7794,7 @@ static void lo_runLoop(LibreOfficeKit* /*pThis*/, SolarMutexGuard aGuard; vcl::lok::registerPollCallbacks(pPollCallback, pWakeCallback, pData); + SfxLokHelper::registerViewCallbacks(); Application::UpdateMainThread(); soffice_main(); } diff --git a/include/comphelper/lok.hxx b/include/comphelper/lok.hxx index d1aa6804f534..0565fa78d6da 100644 --- a/include/comphelper/lok.hxx +++ b/include/comphelper/lok.hxx @@ -137,6 +137,13 @@ COMPHELPER_DLLPUBLIC void setBlockedCommandList(const char* blockedCommandList); COMPHELPER_DLLPUBLIC void setAnyInputCallback(const std::function<bool(void*)>& pAnyInputCallback, void* pData); COMPHELPER_DLLPUBLIC bool anyInput(); + +// These allow setting callbacks, so that set/get of a LOK view is possible even in code that is +// below sfx2. +COMPHELPER_DLLPUBLIC void setViewSetter(std::function<void(int)> pViewSetter); +COMPHELPER_DLLPUBLIC void setView(int nView); +COMPHELPER_DLLPUBLIC void setViewGetter(std::function<int()> pViewGetter); +COMPHELPER_DLLPUBLIC int getView(); } #endif // INCLUDED_COMPHELPER_LOK_HXX diff --git a/include/sfx2/lokhelper.hxx b/include/sfx2/lokhelper.hxx index ec73f7c597f0..2f87faf82e78 100644 --- a/include/sfx2/lokhelper.hxx +++ b/include/sfx2/lokhelper.hxx @@ -255,6 +255,8 @@ public: static void getCommandValues(tools::JsonWriter& rJsonWriter, std::string_view rCommand); /// Parses key-value parameters of rCommand. static std::map<OUString, OUString> parseCommandParameters(std::u16string_view rCommand); + /// Registers function pointers in comphelper/ to set/get of the current LOK view. + static void registerViewCallbacks(); private: static int createView(SfxViewFrame& rViewFrame, ViewShellDocId docId); diff --git a/sfx2/source/view/lokhelper.cxx b/sfx2/source/view/lokhelper.cxx index 5eec80fba576..0ea04c16238f 100644 --- a/sfx2/source/view/lokhelper.cxx +++ b/sfx2/source/view/lokhelper.cxx @@ -1105,6 +1105,16 @@ void SfxLokHelper::notifyOtherViewsUpdatePerViewId(SfxViewShell const* pThisView } } +void SfxLokHelper::registerViewCallbacks() +{ + comphelper::LibreOfficeKit::setViewSetter([](int nView) { + SfxLokHelper::setView(nView); + }); + comphelper::LibreOfficeKit::setViewGetter([]() -> int { + return SfxLokHelper::getView(); + }); +} + namespace { struct LOKAsyncEventData diff --git a/sw/qa/extras/tiledrendering/tiledrendering2.cxx b/sw/qa/extras/tiledrendering/tiledrendering2.cxx index eedd023388ca..5464257a388c 100644 --- a/sw/qa/extras/tiledrendering/tiledrendering2.cxx +++ b/sw/qa/extras/tiledrendering/tiledrendering2.cxx @@ -300,6 +300,7 @@ CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testPDFExportViewSwitch) { // Given a document with 2 views: SwXTextDocument* pXTextDocument = createDoc("to-pdf.odt"); + SfxLokHelper::registerViewCallbacks(); SwDoc* pDoc = pXTextDocument->GetDocShell()->GetDoc(); SwTestViewCallback aView1; SfxLokHelper::createView(); diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx index 06a21d733177..8de62eb4c5d1 100644 --- a/vcl/source/app/svapp.cxx +++ b/vcl/source/app/svapp.cxx @@ -401,7 +401,22 @@ bool Application::Reschedule( bool i_bAllEvents ) SAL_WARN("vcl.schedule", "Application::Reschedule(" << i_bAllEvents << ")"); return false; } - return ImplYield(false, i_bAllEvents); + int nOldView = -1; + if (comphelper::LibreOfficeKit::isActive()) + { + nOldView = comphelper::LibreOfficeKit::getView(); + } + bool bRet = ImplYield(false, i_bAllEvents); + if (comphelper::LibreOfficeKit::isActive()) + { + int nNewView = comphelper::LibreOfficeKit::getView(); + if (nOldView != -1 && nNewView != -1 && nOldView != nNewView) + { + // Yield changed the current view, restore the old value. + comphelper::LibreOfficeKit::setView(nOldView); + } + } + return bRet; } bool Application::IsUseSystemEventLoop()
