summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Vajna <vmiklos@collabora.com>2024-12-20 12:56:15 +0100
committerCaolán McNamara <caolan.mcnamara@collabora.com>2024-12-20 13:24:11 +0100
commit520cc546e2940bdfbc45eab1e569bb06bab17a9c (patch)
tree0624998924dd34b7eb15e1dad5774748987c7d40
parent2c95e7186e053ed5f2e7d8388fbe087fa60636c2 (diff)
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/+/178883 Tested-by: Caolán McNamara <caolan.mcnamara@collabora.com> Reviewed-by: Caolán McNamara <caolan.mcnamara@collabora.com> Tested-by: Jenkins CollaboraOffice <jenkinscollaboraoffice@gmail.com>
-rw-r--r--sfx2/source/doc/guisaveas.cxx9
-rw-r--r--sw/qa/extras/tiledrendering/data/to-pdf.odtbin0 -> 18353 bytes
-rw-r--r--sw/qa/extras/tiledrendering/tiledrendering.cxx49
3 files changed, 56 insertions, 2 deletions
diff --git a/sfx2/source/doc/guisaveas.cxx b/sfx2/source/doc/guisaveas.cxx
index 5773fc732ea9..80cc3256f7bf 100644
--- a/sfx2/source/doc/guisaveas.cxx
+++ b/sfx2/source/doc/guisaveas.cxx
@@ -1806,6 +1806,11 @@ bool SfxStoringHelper::FinishGUIStoreModel(::comphelper::SequenceAsHashMap::cons
}
OSL_ENSURE( aModelData.GetMediaDescr().find( OUString( "Password" ) ) == 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 ) )
@@ -1891,10 +1896,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
--- /dev/null
+++ b/sw/qa/extras/tiledrendering/data/to-pdf.odt
Binary files differ
diff --git a/sw/qa/extras/tiledrendering/tiledrendering.cxx b/sw/qa/extras/tiledrendering/tiledrendering.cxx
index a2c804d20aee..fab70ae40b04 100644
--- a/sw/qa/extras/tiledrendering/tiledrendering.cxx
+++ b/sw/qa/extras/tiledrendering/tiledrendering.cxx
@@ -787,6 +787,7 @@ namespace {
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 = {})
: m_bOwnCursorInvalidated(false),
@@ -973,6 +974,11 @@ namespace {
m_aDocColor = aPayload;
break;
}
+ case LOK_CALLBACK_EXPORT_FILE:
+ {
+ m_aExportFile = aPayload;
+ break;
+ }
}
}
};
@@ -4700,6 +4706,49 @@ CPPUNIT_TEST_FIXTURE(SwTiledRenderingTest, testFormatInsertStartList)
// - Actual : MS Sans Serif
}
+namespace
+{
+/// 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();
/* vim:set shiftwidth=4 softtabstop=4 expandtab: */