summaryrefslogtreecommitdiff
path: root/svx/source/form/fmscriptingenv.cxx
diff options
context:
space:
mode:
authorCaolán McNamara <caolanm@redhat.com>2016-06-21 21:29:25 +0100
committerCaolán McNamara <caolanm@redhat.com>2016-06-22 11:33:58 +0100
commit68cf256f506d4601a2d2cf3ec2d56713afd491e6 (patch)
tree4eb2eaa305fbe62fcc175b8982550d1f1014232c /svx/source/form/fmscriptingenv.cxx
parent8dc2873081bff3fe7107d472a91a24af8b67a87d (diff)
Resolves: tdf#88985 block app from exiting during macro execution
but stop basic execution on the exit attempt, and then resend exit at a safe place when basic execution has stopped Change-Id: I77c43acffa0b82e8125dcb3b10ad9bf0d6dd26c3
Diffstat (limited to 'svx/source/form/fmscriptingenv.cxx')
-rw-r--r--svx/source/form/fmscriptingenv.cxx118
1 files changed, 115 insertions, 3 deletions
diff --git a/svx/source/form/fmscriptingenv.cxx b/svx/source/form/fmscriptingenv.cxx
index 3cc284e481b7..b79d42151394 100644
--- a/svx/source/form/fmscriptingenv.cxx
+++ b/svx/source/form/fmscriptingenv.cxx
@@ -22,14 +22,18 @@
#include "fmscriptingenv.hxx"
#include "svx/fmmodel.hxx"
-#include <com/sun/star/lang/IllegalArgumentException.hpp>
-#include <com/sun/star/script/XScriptListener.hpp>
+#include <com/sun/star/awt/XControl.hpp>
+#include <com/sun/star/frame/Desktop.hpp>
+#include <com/sun/star/frame/XTerminateListener.hpp>
#include <com/sun/star/lang/DisposedException.hpp>
#include <com/sun/star/lang/EventObject.hpp>
-#include <com/sun/star/awt/XControl.hpp>
+#include <com/sun/star/lang/IllegalArgumentException.hpp>
+#include <com/sun/star/lang/XServiceInfo.hpp>
+#include <com/sun/star/script/XScriptListener.hpp>
#include <tools/diagnose_ex.h>
#include <cppuhelper/implbase.hxx>
+#include <cppuhelper/compbase.hxx>
#include <comphelper/processfactory.hxx>
#include <vcl/svapp.hxx>
#include <osl/mutex.hxx>
@@ -764,6 +768,111 @@ namespace svxform
m_pScriptExecutor = nullptr;
}
+ // tdf#88985 If LibreOffice tries to exit during the execution of a macro
+ // then: detect the effort, stop basic execution, block until the macro
+ // returns due to that stop, then restart the quit. This avoids the app
+ // exiting and destroying itself until the macro is parked at a safe place
+ // to do that.
+ class QuitGuard
+ {
+ private:
+
+ class TerminateListener : public cppu::WeakComponentImplHelper<css::frame::XTerminateListener,
+ css::lang::XServiceInfo>
+ {
+ private:
+ css::uno::Reference<css::frame::XDesktop2> m_xDesktop;
+ osl::Mutex maMutex;
+ bool mbQuitBlocked;
+ public:
+ // XTerminateListener
+ virtual void SAL_CALL queryTermination(const css::lang::EventObject& /*rEvent*/)
+ throw(css::frame::TerminationVetoException, css::uno::RuntimeException, std::exception) override
+ {
+ mbQuitBlocked = true;
+ StarBASIC::Stop();
+ throw css::frame::TerminationVetoException();
+ }
+
+ virtual void SAL_CALL notifyTermination(const css::lang::EventObject& /*rEvent*/)
+ throw(css::uno::RuntimeException, std::exception) override
+ {
+ mbQuitBlocked = false;
+ }
+
+ using cppu::WeakComponentImplHelperBase::disposing;
+
+ virtual void SAL_CALL disposing(const css::lang::EventObject& rEvent)
+ throw(css::uno::RuntimeException, std::exception) override
+ {
+ const bool bShutDown = (rEvent.Source == m_xDesktop);
+ if (bShutDown && m_xDesktop.is())
+ {
+ m_xDesktop->removeTerminateListener(this);
+ m_xDesktop.clear();
+ }
+ }
+
+ // XServiceInfo
+ virtual OUString SAL_CALL getImplementationName()
+ throw (css::uno::RuntimeException, std::exception) override
+ {
+ return OUString("com.sun.star.comp.svx.StarBasicQuitGuard");
+ }
+
+ virtual sal_Bool SAL_CALL supportsService(OUString const & ServiceName)
+ throw (css::uno::RuntimeException, std::exception) override
+ {
+ return cppu::supportsService(this, ServiceName);
+ }
+
+ virtual css::uno::Sequence<OUString> SAL_CALL getSupportedServiceNames()
+ throw (css::uno::RuntimeException, std::exception) override
+ {
+ css::uno::Sequence<OUString> aSeq { "com.sun.star.svx.StarBasicQuitGuard" };
+ return aSeq;
+ }
+
+ public:
+ TerminateListener()
+ : cppu::WeakComponentImplHelper<css::frame::XTerminateListener,
+ css::lang::XServiceInfo>(maMutex)
+ , mbQuitBlocked(false)
+ {
+ }
+
+ void start()
+ {
+ css::uno::Reference<css::uno::XComponentContext> xContext(comphelper::getProcessComponentContext());
+ m_xDesktop = css::frame::Desktop::create(xContext);
+ m_xDesktop->addTerminateListener(this);
+ }
+
+ void stop()
+ {
+ if (!m_xDesktop.is())
+ return;
+ m_xDesktop->removeTerminateListener(this);
+ if (mbQuitBlocked)
+ m_xDesktop->terminate();
+ }
+ };
+
+ TerminateListener* mpListener;
+ css::uno::Reference<css::frame::XTerminateListener> mxLifeCycle;
+ public:
+ QuitGuard()
+ : mpListener(new TerminateListener)
+ , mxLifeCycle(mpListener)
+ {
+ mpListener->start();
+ }
+
+ ~QuitGuard()
+ {
+ mpListener->stop();
+ }
+ };
IMPL_LINK_TYPED( FormScriptListener, OnAsyncScriptEvent, void*, p, void )
{
@@ -776,7 +885,10 @@ namespace svxform
::osl::ClearableMutexGuard aGuard( m_aMutex );
if ( !impl_isDisposed_nothrow() )
+ {
+ QuitGuard aQuitGuard;
impl_doFireScriptEvent_nothrow( aGuard, *_pEvent, nullptr );
+ }
}
delete _pEvent;