sfx2/source/doc/guisaveas.cxx                               |    9 ++
 sw/qa/extras/tiledrendering/data/to-pdf.odt                 |binary
 sw/qa/extras/tiledrendering/tiledrendering2.cxx             |   38 ++++++++++++
 sw/qa/extras/tiledrendering/tiledrenderingmodeltestbase.cxx |    6 +
 4 files changed, 51 insertions(+), 2 deletions(-)

New commits:
commit 496c409841d9ee71964af8a8afdc121282e69a63
Author:     Miklos Vajna <vmik...@collabora.com>
AuthorDate: Fri Dec 20 12:56:15 2024 +0100
Commit:     Miklos Vajna <vmik...@collabora.com>
CommitDate: Fri Dec 20 14:40:54 2024 +0100

    cool#10782 sfx2 lok: fix bad view id on PDF export
    
    Have 2 views, view 2 dispatches .uno:ExportDirectToPDF, and sometimes
    view 1 gets the LOK_CALLBACK_EXPORT_FILE callback, which is incorrect.
    
    What happens is that the command gets dispatched correctly, but during
    save the progressbar gets updated in
    framework::StatusIndicatorFactory::end(), which calls
    Application::Reschedule(), which processes LOK jobs on the main loop,
    which may switch back to view 1, so the callback is emitted on that
    view.
    
    Fix the problem by reducing the duration where we work with the "current
    view". We know that initially the command dispatch has the correct
    current view since commit ee7ca8e4ea8ed93655f99e77a9e77032ac830c46
    (cool#7865 sfx2 lok: fix bad view id on async command dispatch,
    2023-12-20), so fetch the current view before the actual filter call and
    work with that view explicitly later.
    
    This is also similar to what SfxObjectShell::ExecFile_Impl() does for
    the bMailPrepareExport case, which also had trouble with GUIStoreModel()
    spinning the main loop.
    
    Change-Id: Id642056aa55831c54e88c61931753c03fa23b6b0
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/178915
    Reviewed-by: Miklos Vajna <vmik...@collabora.com>
    Tested-by: Jenkins

diff --git a/sfx2/source/doc/guisaveas.cxx b/sfx2/source/doc/guisaveas.cxx
index f0d3000a0e0c..adfc6c8345fa 100644
--- a/sfx2/source/doc/guisaveas.cxx
+++ b/sfx2/source/doc/guisaveas.cxx
@@ -1825,6 +1825,11 @@ bool 
SfxStoringHelper::FinishGUIStoreModel(::comphelper::SequenceAsHashMap::cons
     }
 
     OSL_ENSURE( aModelData.GetMediaDescr().find( u"Password"_ustr ) == 
aModelData.GetMediaDescr().end(), "The Password property of MediaDescriptor 
should not be used here!" );
+
+    // Fetch the current view early, saving may spin the main loop, which may 
change the current
+    // view.
+    SfxViewShell* pViewShell = SfxViewShell::Current();
+
     if ( officecfg::Office::Common::Save::Document::EditProperty::get()
       && ( !aModelData.GetStorable()->hasLocation()
           || INetURLObject( aModelData.GetStorable()->getLocation() ) != aURL 
) )
@@ -1966,10 +1971,10 @@ bool 
SfxStoringHelper::FinishGUIStoreModel(::comphelper::SequenceAsHashMap::cons
 
     if ( comphelper::LibreOfficeKit::isActive() )
     {
-        if ( SfxViewShell* pShell = SfxViewShell::Current() )
+        if ( pViewShell )
         {
             OUString sURL = aURL.GetMainURL( 
INetURLObject::DecodeMechanism::NONE );
-            pShell->libreOfficeKitViewCallback( LOK_CALLBACK_EXPORT_FILE, 
sURL.toUtf8() );
+            pViewShell->libreOfficeKitViewCallback( LOK_CALLBACK_EXPORT_FILE, 
sURL.toUtf8() );
         }
     }
 
diff --git a/sw/qa/extras/tiledrendering/data/to-pdf.odt 
b/sw/qa/extras/tiledrendering/data/to-pdf.odt
new file mode 100644
index 000000000000..26e7b01dc980
Binary files /dev/null and b/sw/qa/extras/tiledrendering/data/to-pdf.odt differ
diff --git a/sw/qa/extras/tiledrendering/tiledrendering2.cxx 
b/sw/qa/extras/tiledrendering/tiledrendering2.cxx
index 112d0ce90c1d..0f9591d5afc3 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering2.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering2.cxx
@@ -19,6 +19,7 @@
 #include <sfx2/msgpool.hxx>
 #include <vcl/scheduler.hxx>
 #include <comphelper/propertyvalue.hxx>
+#include <comphelper/dispatchcommand.hxx>
 
 #include <view.hxx>
 #include <IDocumentLayoutAccess.hxx>
@@ -268,6 +269,43 @@ CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, 
testFormatInsertStartList)
     // - Expected: Calibri
     // - Actual  : MS Sans Serif
 }
+
+/// Job on the main loop that switches to the first view.
+class ViewSwitcher
+{
+public:
+    DECL_STATIC_LINK(ViewSwitcher, SwitchView, void*, void);
+};
+
+IMPL_STATIC_LINK_NOARG(ViewSwitcher, SwitchView, void*, void) { 
SfxLokHelper::setView(0); }
+
+CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testPDFExportViewSwitch)
+{
+    // Given a document with 2 views:
+    SwXTextDocument* pXTextDocument = createDoc("to-pdf.odt");
+    SwDoc* pDoc = pXTextDocument->GetDocShell()->GetDoc();
+    ViewCallback aView1;
+    SfxLokHelper::createView();
+    ViewCallback aView2;
+    SwView* pView2 = pDoc->GetDocShell()->GetView();
+    uno::Reference<frame::XFrame> xFrame2 = 
pView2->GetViewFrame().GetFrame().GetFrameInterface();
+
+    // When exporting to PDF on the second view and a job on the main loop 
that switches to the
+    // first view:
+    uno::Sequence<beans::PropertyValue> aPropertyValues = {
+        comphelper::makePropertyValue("SynchronMode", false),
+        comphelper::makePropertyValue("URL", maTempFile.GetURL()),
+    };
+    comphelper::dispatchCommand(".uno:ExportDirectToPDF", xFrame2, 
aPropertyValues);
+    Application::PostUserEvent(LINK(nullptr, ViewSwitcher, SwitchView), 
nullptr);
+    Scheduler::ProcessEventsToIdle();
+
+    // Then make sure the callback is invoked exactly on the second view:
+    // Without the accompanying fix in place, this test failed, as the 
callback was invoked on the
+    // first view.
+    CPPUNIT_ASSERT(aView1.m_aExportFile.isEmpty());
+    CPPUNIT_ASSERT(!aView2.m_aExportFile.isEmpty());
+}
 }
 
 CPPUNIT_PLUGIN_IMPLEMENT();
diff --git a/sw/qa/extras/tiledrendering/tiledrenderingmodeltestbase.cxx 
b/sw/qa/extras/tiledrendering/tiledrenderingmodeltestbase.cxx
index a53770b06cc3..96bfd851ce0c 100644
--- a/sw/qa/extras/tiledrendering/tiledrenderingmodeltestbase.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrenderingmodeltestbase.cxx
@@ -294,6 +294,7 @@ public:
     boost::property_tree::ptree m_aComment;
     std::vector<OString> m_aStateChanges;
     TestLokCallbackWrapper m_callbackWrapper;
+    OString m_aExportFile;
 
     ViewCallback(SfxViewShell* pViewShell = nullptr,
                  std::function<void(ViewCallback&)> const& rBeforeInstallFunc 
= {})
@@ -471,6 +472,11 @@ public:
                 m_aDocColor = aPayload;
                 break;
             }
+            case LOK_CALLBACK_EXPORT_FILE:
+            {
+                m_aExportFile = aPayload;
+                break;
+            }
         }
     }
 };

Reply via email to