[Libreoffice-commits] core.git: Branch 'private/swe/libreoffice-5-2+backports' - framework/source include/vcl uui/source vcl/inc vcl/source
Armin Le Grand
Armin.Le.Grand at cib.de
Fri Aug 25 14:05:16 UTC 2017
framework/source/dispatch/closedispatcher.cxx | 9 +++
framework/source/loadenv/loadenv.cxx | 4 +
include/vcl/dialog.hxx | 17 ++++++
include/vcl/msgbox.hxx | 3 -
include/vcl/svapp.hxx | 6 ++
uui/source/iahndl.cxx | 30 ++++++++++-
vcl/inc/svdata.hxx | 1
vcl/source/app/svapp.cxx | 16 ++++++
vcl/source/window/dialog.cxx | 67 ++++++++++++++++----------
vcl/source/window/msgbox.cxx | 4 -
10 files changed, 124 insertions(+), 33 deletions(-)
New commits:
commit 4a6755c688fb69f8ce47cc89fe49f89860e02e07
Author: Armin Le Grand <Armin.Le.Grand at cib.de>
Date: Thu Aug 24 18:32:38 2017 +0200
Allow non-modal Dialogs during FileImport/Load
When opening a file that triggers Dialogs (e.g. cannot
read/repair/FileType) the Frame from which it was
initialized gets blocked. This irritates quite some
people. Changed this to a non-modal Dialog so that
the user can continue to work with all opened docs,
open new ones, close and print/PDF/export these.
Change-Id: I048d3de3369527cec20d26396b87439254764b8a
Reviewed-on: https://gerrit.libreoffice.org/41534
Tested-by: Jenkins <ci at libreoffice.org>
Reviewed-by: Armin Le Grand <Armin.Le.Grand at cib.de>
diff --git a/framework/source/dispatch/closedispatcher.cxx b/framework/source/dispatch/closedispatcher.cxx
index aa15c28009a1..9aa25190a544 100644
--- a/framework/source/dispatch/closedispatcher.cxx
+++ b/framework/source/dispatch/closedispatcher.cxx
@@ -37,6 +37,7 @@
#include <vcl/svapp.hxx>
#include <vcl/syswin.hxx>
#include <osl/mutex.hxx>
+#include <vcl/dialog.hxx>
#include <unotools/moduleoptions.hxx>
#include <comphelper/processfactory.hxx>
@@ -362,6 +363,14 @@ 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/loadenv/loadenv.cxx b/framework/source/loadenv/loadenv.cxx
index b6f6f4c92178..c789f4d6e957 100644
--- a/framework/source/loadenv/loadenv.cxx
+++ b/framework/source/loadenv/loadenv.cxx
@@ -378,6 +378,10 @@ 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)
diff --git a/include/vcl/dialog.hxx b/include/vcl/dialog.hxx
index 3aa38f543802..87588d50c85d 100644
--- a/include/vcl/dialog.hxx
+++ b/include/vcl/dialog.hxx
@@ -33,7 +33,17 @@ class VclButtonBox;
class VCL_DLLPUBLIC Dialog : public SystemWindow
{
public:
- enum class InitFlag { Default, NoParent };
+ enum class InitFlag
+ {
+ /** 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
+ };
private:
VclPtr<Dialog> mpPrevExecuteDlg;
@@ -83,6 +93,10 @@ public:
virtual void dispose() override;
virtual bool Notify( NotifyEvent& rNEvt ) override;
+
+ // get the default parent for a dialog as is done in standard initialization
+ static vcl::Window* GetDefaultParent(WinBits nStyle);
+
virtual void StateChanged( StateChangedType nStateChange ) override;
virtual void DataChanged( const DataChangedEvent& rDCEvt ) override;
@@ -111,6 +125,7 @@ public:
void EndDialog( long nResult = 0 );
static void EndAllDialogs( vcl::Window* pParent=nullptr );
+ static bool AreDialogsOpen();
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 5ac566f435d9..0f526f618fe6 100644
--- a/include/vcl/msgbox.hxx
+++ b/include/vcl/msgbox.hxx
@@ -47,7 +47,8 @@ protected:
public:
MessBox( vcl::Window* pParent, WinBits nStyle,
- const OUString& rTitle, const OUString& rMessage );
+ const OUString& rTitle, const OUString& rMessage,
+ Dialog::InitFlag eInitFlag = Dialog::InitFlag::NoParentCentered);
virtual ~MessBox();
virtual void dispose() override;
diff --git a/include/vcl/svapp.hxx b/include/vcl/svapp.hxx
index 34b659fa7f33..2be63c268198 100644
--- a/include/vcl/svapp.hxx
+++ b/include/vcl/svapp.hxx
@@ -1451,6 +1451,12 @@ 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 2321bdf19361..b53f5b474323 100644
--- a/uui/source/iahndl.cxx
+++ b/uui/source/iahndl.cxx
@@ -998,11 +998,33 @@ executeMessageBox(
vcl::Window * pParent,
OUString const & rTitle,
OUString const & rMessage,
- WinBits nButtonMask )
+ WinBits nButtonMask,
+ Dialog::InitFlag eInitFlag)
{
SolarMutexGuard aGuard;
+ ScopedVclPtrInstance< MessBox > xBox(pParent, nButtonMask, rTitle, rMessage, eInitFlag);
- ScopedVclPtrInstance< MessBox > xBox(pParent, nButtonMask, rTitle, rMessage);
+ 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)));
+ }
+ }
sal_uInt16 aResult = xBox->Execute();
switch( aResult )
@@ -1154,7 +1176,7 @@ UUIInteractionHelper::handleGenericErrorRequest(
aTitle += aErrTitle;
executeMessageBox(
- getParentProperty(), aTitle, aErrorString, WB_OK );
+ getParentProperty(), aTitle, aErrorString, WB_OK, Dialog::InitFlag::NoParentCentered);
}
else
ErrorHandler::HandleError(nErrorCode);
@@ -1278,7 +1300,7 @@ UUIInteractionHelper::handleBrokenPackageRequest(
utl::ConfigManager::getProductVersion() );
switch (
- executeMessageBox( getParentProperty(), title, aMessage, nButtonMask ) )
+ executeMessageBox( getParentProperty(), title, aMessage, nButtonMask, Dialog::InitFlag::NoParentCentered) )
{
case ERRCODE_BUTTON_OK:
OSL_ENSURE( xAbort.is(), "unexpected situation" );
diff --git a/vcl/inc/svdata.hxx b/vcl/inc/svdata.hxx
index 4b1c1d7b3fa1..fb6c71281eeb 100644
--- a/vcl/inc/svdata.hxx
+++ b/vcl/inc/svdata.hxx
@@ -147,6 +147,7 @@ struct ImplSVAppData
bool mbInAppMain = false; // is Application::Main() on stack
bool mbInAppExecute = false; // is Application::Execute() on stack
bool mbAppQuit = false; // is Application::Quit() called
+ bool mbShutdownDelayed = false;
bool mbSettingsInit = false; // true: Settings are initialized
Application::DialogCancelMode meDialogCancel; // true: All Dialog::Execute() calls will be terminated immediately with return false
diff --git a/vcl/source/app/svapp.cxx b/vcl/source/app/svapp.cxx
index 6af3c7c1c7cf..fc6fefc7d958 100644
--- a/vcl/source/app/svapp.cxx
+++ b/vcl/source/app/svapp.cxx
@@ -1816,4 +1816,20 @@ 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 2cebcb16fe0e..95fed10ab0a6 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -365,6 +365,36 @@ void Dialog::ImplInitDialogData()
mpDialogImpl = new DialogImpl;
}
+vcl::Window* Dialog::GetDefaultParent(WinBits nStyle)
+{
+ vcl::Window* pParent = Application::GetDefDialogParent();
+ if (!pParent && !(nStyle & WB_SYSTEMWINDOW))
+ pParent = ImplGetSVData()->maWinData.mpAppWin;
+
+ // If Parent is disabled, then we search for a modal dialog
+ // in this frame
+ if (pParent && (!pParent->IsInputEnabled() || pParent->IsInModalMode()))
+ {
+ ImplSVData* pSVData = ImplGetSVData();
+ Dialog* pExeDlg = pSVData->maWinData.mpLastExecuteDlg;
+ while (pExeDlg)
+ {
+ // only if visible and enabled
+ if (pParent->ImplGetFirstOverlapWindow()->IsWindowOrChild(pExeDlg, true) &&
+ pExeDlg->IsReallyVisible() &&
+ pExeDlg->IsEnabled() && pExeDlg->IsInputEnabled() && !pExeDlg->IsInModalMode())
+ {
+ pParent = pExeDlg;
+ break;
+ }
+
+ pExeDlg = pExeDlg->mpPrevExecuteDlg;
+ }
+ }
+
+ return pParent;
+}
+
void Dialog::ImplInit( vcl::Window* pParent, WinBits nStyle, InitFlag eFlag )
{
SystemWindowFlags nSysWinMode = Application::GetSystemWindowMode();
@@ -376,34 +406,13 @@ void Dialog::ImplInit( vcl::Window* pParent, WinBits nStyle, InitFlag eFlag )
// Now, all Dialogs are per default system windows !!!
nStyle |= WB_SYSTEMWINDOW;
- if (eFlag == InitFlag::NoParent)
+ if (InitFlag::NoParent == eFlag || InitFlag::NoParentCentered == eFlag)
+ {
pParent = nullptr;
+ }
else if (!pParent) // parent is NULL: get the default Dialog parent
{
- pParent = Application::GetDefDialogParent();
- if ( !pParent && !(nStyle & WB_SYSTEMWINDOW) )
- pParent = ImplGetSVData()->maWinData.mpAppWin;
-
- // If Parent is disabled, then we search for a modal dialog
- // in this frame
- if ( pParent && (!pParent->IsInputEnabled() || pParent->IsInModalMode()) )
- {
- ImplSVData* pSVData = ImplGetSVData();
- Dialog* pExeDlg = pSVData->maWinData.mpLastExecuteDlg;
- while ( pExeDlg )
- {
- // only if visible and enabled
- if ( pParent->ImplGetFirstOverlapWindow()->IsWindowOrChild( pExeDlg, true ) &&
- pExeDlg->IsReallyVisible() &&
- pExeDlg->IsEnabled() && pExeDlg->IsInputEnabled() && !pExeDlg->IsInModalMode() )
- {
- pParent = pExeDlg;
- break;
- }
-
- pExeDlg = pExeDlg->mpPrevExecuteDlg;
- }
- }
+ pParent = Dialog::GetDefaultParent(nStyle);
}
if ( !pParent || (nStyle & WB_SYSTEMWINDOW) ||
@@ -1000,6 +1009,14 @@ 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 7fb7f28dd12b..f6fd26773624 100644
--- a/vcl/source/window/msgbox.cxx
+++ b/vcl/source/window/msgbox.cxx
@@ -138,12 +138,12 @@ void MessBox::ImplInitButtons()
}
MessBox::MessBox( vcl::Window* pParent, WinBits nStyle,
- const OUString& rTitle, const OUString& rMessage ) :
+ const OUString& rTitle, const OUString& rMessage, Dialog::InitFlag eInitFlag) :
ButtonDialog( WINDOW_MESSBOX ),
maMessText( rMessage )
{
ImplInitMessBoxData();
- ImplInit( pParent, nStyle | WB_MOVEABLE | WB_HORZ | WB_CENTER );
+ ImplInit( pParent, nStyle | WB_MOVEABLE | WB_HORZ | WB_CENTER, eInitFlag);
ImplInitButtons();
if ( !rTitle.isEmpty() )
More information about the Libreoffice-commits
mailing list