framework/Library_fwe.mk | 1 framework/source/dispatch/closedispatcher.cxx | 10 framework/source/fwe/interaction/preventduplicateinteraction.cxx | 10 framework/source/loadenv/loadenv.cxx | 6 include/framework/preventduplicateinteraction.hxx | 112 ++++++++++ include/vcl/dialog.hxx | 10 include/vcl/msgbox.hxx | 3 include/vcl/svapp.hxx | 6 uui/source/iahndl.cxx | 33 -- vcl/source/app/svapp.cxx | 16 - vcl/source/window/dialog.cxx | 12 - vcl/source/window/msgbox.cxx | 8 12 files changed, 138 insertions(+), 89 deletions(-)
New commits: commit 77359a2350cf121937d5d646c17621557ab832fe Author: Caolán McNamara <caol...@redhat.com> Date: Thu Nov 2 17:23:00 2017 +0000 Resolves: tdf#113160 changing all warning dialogs to non-modal is unsafe existing code doesn't expect that so stuff crashes partial revert of... commit db6b703d391838c481fd090065f6d329edcd4efa Date: Thu Aug 24 18:32:38 2017 +0200 Allow non-modal Dialogs during FileImport/Load Change-Id: I152feb849186cf035664a700d3f94ee049cdf6d3 Reviewed-on: https://gerrit.libreoffice.org/44227 Reviewed-by: Caolán McNamara <caol...@redhat.com> Tested-by: Caolán McNamara <caol...@redhat.com> Related: tdf#113160 set a temporary dialog parent during type detection to get warning dialogs that don't block the existing windows but whose lifecycle can be controlled to avoid crashes during exit Change-Id: I57965301c3d8a031acb33e83bf7715fe132385d0 Reviewed-on: https://gerrit.libreoffice.org/45044 Reviewed-by: Caolán McNamara <caol...@redhat.com> Tested-by: Caolán McNamara <caol...@redhat.com> Reviewed-on: https://gerrit.libreoffice.org/45400 Reviewed-by: Thorsten Behrens <thorsten.behr...@cib.de> Tested-by: Thorsten Behrens <thorsten.behr...@cib.de> diff --git a/framework/Library_fwe.mk b/framework/Library_fwe.mk index 0559236b2bad..d94cb100a975 100644 --- a/framework/Library_fwe.mk +++ b/framework/Library_fwe.mk @@ -46,6 +46,7 @@ $(eval $(call gb_Library_use_libraries,fwe,\ svl \ svt \ tl \ + tk \ utl \ vcl \ $(gb_UWINAPI) \ diff --git a/framework/source/dispatch/closedispatcher.cxx b/framework/source/dispatch/closedispatcher.cxx index 9aa25190a544..96df4fe9d9e5 100644 --- a/framework/source/dispatch/closedispatcher.cxx +++ b/framework/source/dispatch/closedispatcher.cxx @@ -36,8 +36,6 @@ #include <vcl/window.hxx> #include <vcl/svapp.hxx> #include <vcl/syswin.hxx> -#include <osl/mutex.hxx> -#include <vcl/dialog.hxx> #include <unotools/moduleoptions.hxx> #include <comphelper/processfactory.hxx> @@ -363,14 +361,6 @@ IMPL_LINK_NOARG_TYPED(CloseDispatcher, impl_asyncCallback, LinkParamNone*, void) } } - // if we still have dialogs open, temporary suppress termination - if (bTerminateApp && Dialog::AreDialogsOpen()) - { - Application::SetShutdownDelayed(); - bCloseFrame = true; - bTerminateApp = false; - } - // Do it now ... bool bSuccess = false; if (bCloseFrame) diff --git a/framework/source/fwe/interaction/preventduplicateinteraction.cxx b/framework/source/fwe/interaction/preventduplicateinteraction.cxx index 818fdfe2122a..9e43e1b1d44f 100644 --- a/framework/source/fwe/interaction/preventduplicateinteraction.cxx +++ b/framework/source/fwe/interaction/preventduplicateinteraction.cxx @@ -19,6 +19,7 @@ #include <framework/preventduplicateinteraction.hxx> +#include <comphelper/processfactory.hxx> #include <osl/diagnose.h> #include <com/sun/star/task/InteractionHandler.hpp> @@ -53,7 +54,9 @@ void PreventDuplicateInteraction::useDefaultUUIHandler() aLock.clear(); // <- SAFE - css::uno::Reference< css::task::XInteractionHandler > xHandler( css::task::InteractionHandler::createWithParent( m_xContext, nullptr ), css::uno::UNO_QUERY_THROW ); + m_xWarningDialogsParent.reset(new WarningDialogsParentScope(m_xContext)); + css::uno::Reference<css::task::XInteractionHandler> xHandler(css::task::InteractionHandler::createWithParent( + m_xContext, m_xWarningDialogsParent->GetDialogParent()), css::uno::UNO_QUERY_THROW); // SAFE -> aLock.reset(); @@ -236,6 +239,11 @@ bool PreventDuplicateInteraction::getInteractionInfo(const css::uno::Type& return false; } +IMPL_STATIC_LINK_NOARG_TYPED(WarningDialogsParent, TerminateDesktop, void*, void) +{ + css::frame::Desktop::create(comphelper::getProcessComponentContext())->terminate(); +} + } // namespace framework /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/framework/source/loadenv/loadenv.cxx b/framework/source/loadenv/loadenv.cxx index c789f4d6e957..5e51c42bee83 100644 --- a/framework/source/loadenv/loadenv.cxx +++ b/framework/source/loadenv/loadenv.cxx @@ -378,10 +378,6 @@ void LoadEnv::startLoading() if (!bStarted) bStarted = impl_loadContent(); - // This may have triggered Dialogs (error cases) that may have - // delayed the shutdown, so give delayed shutdown a chance - Application::TriggerShutdownDelayed(); - // not started => general error // We can't say - what was the reason for. if (!bStarted) @@ -1077,7 +1073,7 @@ bool LoadEnv::impl_loadContent() if (!bHidden && !bMinimized && !bPreview && !xProgress.is()) { - // Note: its an optional interface! + // Note: it's an optional interface! css::uno::Reference< css::task::XStatusIndicatorFactory > xProgressFactory(xTargetFrame, css::uno::UNO_QUERY); if (xProgressFactory.is()) { diff --git a/include/framework/preventduplicateinteraction.hxx b/include/framework/preventduplicateinteraction.hxx index cf6ac0058eda..cd3d7438c785 100644 --- a/include/framework/preventduplicateinteraction.hxx +++ b/include/framework/preventduplicateinteraction.hxx @@ -24,17 +24,127 @@ #include <vector> +#include <com/sun/star/frame/Desktop.hpp> +#include <com/sun/star/frame/TerminationVetoException.hpp> +#include <com/sun/star/frame/XTerminateListener2.hpp> #include <com/sun/star/task/XInteractionHandler2.hpp> #include <com/sun/star/task/XInteractionRequest.hpp> +#include <cppuhelper/compbase.hxx> #include <cppuhelper/implbase.hxx> +#include <sfx2/app.hxx> +#include <toolkit/helper/vclunohelper.hxx> +#include <vcl/dialog.hxx> +#include <vcl/svapp.hxx> +#include <vcl/wrkwin.hxx> + namespace com { namespace sun { namespace star { namespace uno { class XComponentContext; } } } } namespace framework{ +inline void closedialogs(SystemWindow& rTopLevel, bool bCloseRoot) +{ + for (vcl::Window *pChild = rTopLevel.GetWindow(GetWindowType::FirstTopWindowChild); pChild; pChild = rTopLevel.GetWindow(GetWindowType::NextTopWindowSibling)) + closedialogs(dynamic_cast<SystemWindow&>(*pChild), true); + if (bCloseRoot) + rTopLevel.Close(); +} + +// This is intended to be the parent for any warning dialogs launched +// during the load of a document so that those dialogs are modal to +// this window and don't block any existing windows. +// +// If there are dialog children open on exit then veto termination, +// close the topmost dialog and retry termination. +class WarningDialogsParent : + public cppu::WeakComponentImplHelper<css::frame::XTerminateListener> +{ +private: + osl::Mutex m_aLock; + VclPtr<WorkWindow> m_xWin; + css::uno::Reference<css::awt::XWindow> m_xInterface; + +private: + + DECL_STATIC_LINK_TYPED(WarningDialogsParent, TerminateDesktop, void*, void); + + void closewarningdialogs() + { + if (!m_xWin) + return; + SolarMutexGuard aSolarGuard; + closedialogs(dynamic_cast<SystemWindow&>(*m_xWin), false); + } + +public: + + using cppu::WeakComponentImplHelperBase::disposing; + virtual void SAL_CALL disposing(const css::lang::EventObject&) override + { + } + + // XTerminateListener + virtual void SAL_CALL queryTermination(const css::lang::EventObject&) override + { + closewarningdialogs(); + Application::PostUserEvent(LINK(this, WarningDialogsParent, TerminateDesktop)); + throw css::frame::TerminationVetoException(); + } + + virtual void SAL_CALL notifyTermination(const css::lang::EventObject&) override + { + } + +public: + WarningDialogsParent() + : cppu::WeakComponentImplHelper<css::frame::XTerminateListener>(m_aLock) + { + SolarMutexGuard aSolarGuard; + m_xWin = VclPtr<WorkWindow>::Create(nullptr, WB_STDWORK); + m_xWin->SetText("dialog parent for warning dialogs during load"); + m_xInterface = VCLUnoHelper::GetInterface(m_xWin); + } + + virtual ~WarningDialogsParent() override + { + closewarningdialogs(); + m_xWin.disposeAndClear(); + } + + const css::uno::Reference<css::awt::XWindow>& GetDialogParent() const + { + return m_xInterface; + } +}; + +class WarningDialogsParentScope +{ +private: + css::uno::Reference<css::frame::XDesktop> m_xDesktop; + rtl::Reference<WarningDialogsParent> m_xListener; + +public: + WarningDialogsParentScope(const css::uno::Reference<css::uno::XComponentContext>& rContext) + : m_xDesktop(css::frame::Desktop::create(rContext), css::uno::UNO_QUERY_THROW) + , m_xListener(new WarningDialogsParent) + { + m_xDesktop->addTerminateListener(m_xListener.get()); + } + + const css::uno::Reference<css::awt::XWindow>& GetDialogParent() const + { + return m_xListener->GetDialogParent(); + } + + ~WarningDialogsParentScope() + { + m_xDesktop->removeTerminateListener(m_xListener.get()); + } +}; + /** @short Prevent us from showing the same interaction more than once during the same transaction. @@ -101,6 +211,8 @@ class FWE_DLLPUBLIC PreventDuplicateInteraction : private ThreadHelpBase2 if it's not blocked. */ css::uno::Reference< css::task::XInteractionHandler > m_xHandler; + std::unique_ptr<WarningDialogsParentScope> m_xWarningDialogsParent; + /** This list describe which and how incoming interactions must be handled. Further it contains all collected information after this interaction object was used.*/ diff --git a/include/vcl/dialog.hxx b/include/vcl/dialog.hxx index 87588d50c85d..34e03fc03a99 100644 --- a/include/vcl/dialog.hxx +++ b/include/vcl/dialog.hxx @@ -38,11 +38,8 @@ public: /** Use given parent or get a default one using GetDefaultParent(...) */ Default, - /** Suppress Parent so that Parent is not blocked (kind of modal mode) */ - NoParent, - - /** Suppress Parent (no modal, see above) and additionally center on default parent */ - NoParentCentered + /** No Parent */ + NoParent }; private: @@ -124,8 +121,7 @@ public: void EndDialog( long nResult = 0 ); - static void EndAllDialogs( vcl::Window* pParent=nullptr ); - static bool AreDialogsOpen(); + static void EndAllDialogs( vcl::Window const * pParent ); void GetDrawWindowBorder( sal_Int32& rLeftBorder, sal_Int32& rTopBorder, sal_Int32& rRightBorder, sal_Int32& rBottomBorder ) const; diff --git a/include/vcl/msgbox.hxx b/include/vcl/msgbox.hxx index 0f526f618fe6..f3351664574c 100644 --- a/include/vcl/msgbox.hxx +++ b/include/vcl/msgbox.hxx @@ -47,8 +47,7 @@ protected: public: MessBox( vcl::Window* pParent, WinBits nStyle, - const OUString& rTitle, const OUString& rMessage, - Dialog::InitFlag eInitFlag = Dialog::InitFlag::NoParentCentered); + const OUString& rTitle, const OUString& rMessage); virtual ~MessBox(); virtual void dispose() override; diff --git a/include/vcl/svapp.hxx b/include/vcl/svapp.hxx index 2be63c268198..34b659fa7f33 100644 --- a/include/vcl/svapp.hxx +++ b/include/vcl/svapp.hxx @@ -1451,12 +1451,6 @@ public: // For vclbootstrapprotector: static void setDeInitHook(Link<LinkParamNone*,void> const & hook); - // for delayed shutdown: set using SetShutdownDelayed, then - // trigger using TriggerShutdownDelayed which may actually shutdown - // when SetShutdownDelayed is set - static void SetShutdownDelayed(); - static void TriggerShutdownDelayed(); - private: DECL_STATIC_LINK_TYPED( Application, PostEventHandler, void*, void ); }; diff --git a/uui/source/iahndl.cxx b/uui/source/iahndl.cxx index b53f5b474323..e94947ecc233 100644 --- a/uui/source/iahndl.cxx +++ b/uui/source/iahndl.cxx @@ -998,33 +998,10 @@ executeMessageBox( vcl::Window * pParent, OUString const & rTitle, OUString const & rMessage, - WinBits nButtonMask, - Dialog::InitFlag eInitFlag) + WinBits nStyle) { SolarMutexGuard aGuard; - ScopedVclPtrInstance< MessBox > xBox(pParent, nButtonMask, rTitle, rMessage, eInitFlag); - - if (Dialog::InitFlag::NoParentCentered == eInitFlag) - { - vcl::Window* pDefaultParent = Dialog::GetDefaultParent(nButtonMask); - - if (pDefaultParent) - { - // need to 'Show' to have the following tasks do someting, does - // not work without and may even stumble on nullptrs/errors - xBox->Show(); - - // center on parent window - const Point aP(pDefaultParent->GetPosPixel()); - const Size aS(pDefaultParent->GetSizePixel()); - const Size aMySize(xBox->GetSizePixel()); - - xBox->SetPosPixel( - Point( - aP.X() + ((aS.Width() - aMySize.Width()) >> 1), - aP.Y() + ((aS.Height() - aMySize.Height()) >> 1))); - } - } + ScopedVclPtrInstance< MessBox > xBox(pParent, nStyle, rTitle, rMessage); sal_uInt16 aResult = xBox->Execute(); switch( aResult ) @@ -1175,8 +1152,7 @@ UUIInteractionHelper::handleGenericErrorRequest( aTitle += " - " ; aTitle += aErrTitle; - executeMessageBox( - getParentProperty(), aTitle, aErrorString, WB_OK, Dialog::InitFlag::NoParentCentered); + executeMessageBox(getParentProperty(), aTitle, aErrorString, WB_OK); } else ErrorHandler::HandleError(nErrorCode); @@ -1299,8 +1275,7 @@ UUIInteractionHelper::handleBrokenPackageRequest( " " + utl::ConfigManager::getProductVersion() ); - switch ( - executeMessageBox( getParentProperty(), title, aMessage, nButtonMask, Dialog::InitFlag::NoParentCentered) ) + switch (executeMessageBox(getParentProperty(), title, aMessage, nButtonMask)) { case ERRCODE_BUTTON_OK: OSL_ENSURE( xAbort.is(), "unexpected situation" ); diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx index fc6fefc7d958..6af3c7c1c7cf 100644 --- a/vcl/source/app/svapp.cxx +++ b/vcl/source/app/svapp.cxx @@ -1816,20 +1816,4 @@ void Application::setDeInitHook(Link<LinkParamNone*,void> const & hook) { pSVData->maAppData.mbInAppMain = true; } -void Application::SetShutdownDelayed() -{ - ImplSVData * pSVData = ImplGetSVData(); - pSVData->maAppData.mbShutdownDelayed = true; -} - -void Application::TriggerShutdownDelayed() -{ - ImplSVData * pSVData = ImplGetSVData(); - - if (pSVData->maAppData.mbShutdownDelayed && !Dialog::AreDialogsOpen()) - { - Application::PostUserEvent(LINK(nullptr, ImplSVAppData, ImplPrepareExitMsg)); - } -} - /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx index 95fed10ab0a6..d0aa084e777e 100644 --- a/vcl/source/window/dialog.cxx +++ b/vcl/source/window/dialog.cxx @@ -406,7 +406,7 @@ void Dialog::ImplInit( vcl::Window* pParent, WinBits nStyle, InitFlag eFlag ) // Now, all Dialogs are per default system windows !!! nStyle |= WB_SYSTEMWINDOW; - if (InitFlag::NoParent == eFlag || InitFlag::NoParentCentered == eFlag) + if (InitFlag::NoParent == eFlag) { pParent = nullptr; } @@ -992,7 +992,7 @@ long Dialog::GetResult() const return mpDialogImpl->mnResult; } -void Dialog::EndAllDialogs( vcl::Window* pParent ) +void Dialog::EndAllDialogs( vcl::Window const * pParent ) { ImplSVData* pSVData = ImplGetSVData(); Dialog* pTempModDialog; @@ -1009,14 +1009,6 @@ void Dialog::EndAllDialogs( vcl::Window* pParent ) } } -bool Dialog::AreDialogsOpen() -{ - ImplSVData* pSVData = ImplGetSVData(); - Dialog* pModDialog = pSVData->maWinData.mpLastExecuteDlg; - - return (nullptr != pModDialog); -} - void Dialog::SetModalInputMode( bool bModal ) { if ( bModal == mbModalMode ) diff --git a/vcl/source/window/msgbox.cxx b/vcl/source/window/msgbox.cxx index f6fd26773624..172c9870889c 100644 --- a/vcl/source/window/msgbox.cxx +++ b/vcl/source/window/msgbox.cxx @@ -138,12 +138,14 @@ void MessBox::ImplInitButtons() } MessBox::MessBox( vcl::Window* pParent, WinBits nStyle, - const OUString& rTitle, const OUString& rMessage, Dialog::InitFlag eInitFlag) : + const OUString& rTitle, const OUString& rMessage) : ButtonDialog( WINDOW_MESSBOX ), - maMessText( rMessage ) + maMessText( rMessage ), + mbHelpBtn( false ), + mbCheck( false ) { ImplInitMessBoxData(); - ImplInit( pParent, nStyle | WB_MOVEABLE | WB_HORZ | WB_CENTER, eInitFlag); + ImplInit( pParent, nStyle | WB_MOVEABLE | WB_HORZ | WB_CENTER); ImplInitButtons(); if ( !rTitle.isEmpty() )
_______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits