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/tiledrendering.cxx | 1 vcl/source/app/svapp.cxx | 17 ++++++++++++ 7 files changed, 70 insertions(+), 1 deletion(-)
New commits: commit 0bbfe4f8e4531b83aee9c84ca66db3672271ea48 Author: Miklos Vajna <vmik...@collabora.com> AuthorDate: Thu Jan 2 16:18:03 2025 +0100 Commit: Miklos Vajna <vmik...@collabora.com> CommitDate: Wed Jan 8 14:20:23 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/+/179623 Reviewed-by: Caolán McNamara <caolan.mcnam...@collabora.com> Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoff...@gmail.com> diff --git a/comphelper/source/misc/lok.cxx b/comphelper/source/misc/lok.cxx index 8f0f61df3218..b576b340e6b7 100644 --- a/comphelper/source/misc/lok.cxx +++ b/comphelper/source/misc/lok.cxx @@ -42,6 +42,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 { @@ -349,6 +352,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 25d7e3f94cf3..a7c77c9534ed 100644 --- a/desktop/source/lib/init.cxx +++ b/desktop/source/lib/init.cxx @@ -7842,6 +7842,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 7f1e866cf5a5..6b83c3d3b6df 100644 --- a/include/comphelper/lok.hxx +++ b/include/comphelper/lok.hxx @@ -141,6 +141,13 @@ COMPHELPER_DLLPUBLIC void setBlockedCommandList(const char* blockedCommandList); COMPHELPER_DLLPUBLIC void setAnyInputCallback(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 2bd132da11bc..274d96915527 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 pamaters 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 ba00e0898234..77d39d22f2e0 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/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx index fab70ae40b04..0f4cac7793cc 100644 --- a/sw/qa/extras/tiledrendering/tiledrendering.cxx +++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx @@ -4725,6 +4725,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(); ViewCallback aView1; SfxLokHelper::createView(); diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx index 55978909a480..c04ecee44be2 100644 --- a/vcl/source/app/svapp.cxx +++ b/vcl/source/app/svapp.cxx @@ -412,7 +412,22 @@ bool Application::Reschedule( bool i_bAllEvents ) SAL_WARN("vcl.schedule", "Application::Reschedule(" << i_bAllEvents << ")"); std::abort(); } - 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::IsOnSystemEventLoop()