[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