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()

Reply via email to