add a Dialog::runAsync for the non-controller case

.. and use it to make the solver warning dialogs async

Change-Id: I3589a1d3ae58190bf545bac1e2a95f81a114d44f
Reviewed-on: https://gerrit.libreoffice.org/66896
Tested-by: Jenkins
Reviewed-by: Noel Grandin <noel.grandin@collabora.co.uk>
diff --git a/include/vcl/abstdlg.hxx b/include/vcl/abstdlg.hxx
index f000d92..71369c9 100644
--- a/include/vcl/abstdlg.hxx
+++ b/include/vcl/abstdlg.hxx
@@ -37,6 +37,7 @@ class Dialog;
class BitmapEx;
namespace weld
{
    class Dialog;
    class DialogController;
    class Window;
}
@@ -54,8 +55,12 @@ public:
    virtual short       Execute() = 0;

    struct AsyncContext {
        // for the case where the owner is the dialog itself, and the dialog is an unwelded VclPtr based dialog
        VclPtr<VclReferenceBase> mxOwner;
        std::shared_ptr<weld::DialogController> mxOwnerDialog;
        // for the case where the dialog is welded, and owned by a DialogController
        std::shared_ptr<weld::DialogController> mxOwnerDialogController;
        // for the case where the dialog is welded, and is running async without a DialogController
        std::shared_ptr<weld::Dialog> mxOwnerSelf;
        std::function<void(sal_Int32)> maEndDialogFn;
        bool isSet() { return !!maEndDialogFn; }
    };
diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx
index 91e77ce..ea5576c 100644
--- a/include/vcl/weld.hxx
+++ b/include/vcl/weld.hxx
@@ -305,6 +305,8 @@ private:

public:
    virtual int run() = 0;
    // Run async without a controller
    virtual bool runAsync(const std::function<void(sal_Int32)>& func) = 0;
    virtual void response(int response) = 0;
    virtual void add_button(const OUString& rText, int response, const OString& rHelpId = OString())
        = 0;
diff --git a/sc/source/ui/miscdlgs/solvrdlg.cxx b/sc/source/ui/miscdlgs/solvrdlg.cxx
index c648029..4ed6da3 100644
--- a/sc/source/ui/miscdlgs/solvrdlg.cxx
+++ b/sc/source/ui/miscdlgs/solvrdlg.cxx
@@ -33,12 +33,12 @@

namespace
{
    void lclErrorDialog(weld::Window* pParent, const OUString& rString)
    void lclErrorDialog(weld::Window* pParent, const OUString& rString, const std::function<void(sal_Int32)>& func)
    {
        std::unique_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent,
        std::shared_ptr<weld::MessageDialog> xBox(Application::CreateMessageDialog(pParent,
                                                  VclMessageType::Warning, VclButtonsType::Ok,
                                                  rString));
        xBox->run();
        xBox->runAsync(func);
    }
}

@@ -166,23 +166,31 @@ void ScSolverDlg::RaiseError( ScSolverErr eError )
    switch ( eError )
    {
        case SOLVERR_NOFORMULA:
            lclErrorDialog(GetFrameWeld() , errMsgNoFormula);
            m_pEdFormulaCell->GrabFocus();
            lclErrorDialog(GetFrameWeld(), errMsgNoFormula,
                [this](sal_Int32 /*nResult*/) {
                    m_pEdFormulaCell->GrabFocus();
                });
            break;

        case SOLVERR_INVALID_FORMULA:
            lclErrorDialog(GetFrameWeld(), errMsgInvalidForm);
            m_pEdFormulaCell->GrabFocus();
            lclErrorDialog(GetFrameWeld(), errMsgInvalidForm,
                [this](sal_Int32 /*nResult*/) {
                    m_pEdFormulaCell->GrabFocus();
                });
            break;

        case SOLVERR_INVALID_VARIABLE:
            lclErrorDialog(GetFrameWeld(), errMsgInvalidVar);
            m_pEdVariableCell->GrabFocus();
            lclErrorDialog(GetFrameWeld(), errMsgInvalidVar,
                [this](sal_Int32 /*nResult*/) {
                    m_pEdVariableCell->GrabFocus();
                });
            break;

        case SOLVERR_INVALID_TARGETVALUE:
            lclErrorDialog(GetFrameWeld(), errMsgInvalidVal);
            m_pEdTargetVal->GrabFocus();
            lclErrorDialog(GetFrameWeld(), errMsgInvalidVal,
                [this](sal_Int32 /*nResult*/) {
                    m_pEdTargetVal->GrabFocus();
                });
            break;
    }
}
diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx
index e1087b4..823c4bb 100644
--- a/vcl/source/app/salvtables.cxx
+++ b/vcl/source/app/salvtables.cxx
@@ -883,7 +883,15 @@ public:
    virtual bool runAsync(std::shared_ptr<weld::DialogController> aOwner, const std::function<void(sal_Int32)> &rEndDialogFn) override
    {
        VclAbstractDialog::AsyncContext aCtx;
        aCtx.mxOwnerDialog = aOwner;
        aCtx.mxOwnerDialogController = aOwner;
        aCtx.maEndDialogFn = rEndDialogFn;
        return m_xDialog->StartExecuteAsync(aCtx);
    }

    virtual bool runAsync(const std::function<void(sal_Int32)> &rEndDialogFn) override
    {
        VclAbstractDialog::AsyncContext aCtx;
        aCtx.mxOwnerSelf.reset(this);
        aCtx.maEndDialogFn = rEndDialogFn;
        return m_xDialog->StartExecuteAsync(aCtx);
    }
diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx
index af49c58..0798c63 100644
--- a/vcl/source/window/dialog.cxx
+++ b/vcl/source/window/dialog.cxx
@@ -1071,7 +1071,8 @@ bool Dialog::StartExecuteAsync( VclAbstractDialog::AsyncContext &rCtx )
    if (!ImplStartExecute())
    {
        rCtx.mxOwner.disposeAndClear();
        rCtx.mxOwnerDialog.reset();
        rCtx.mxOwnerDialogController.reset();
        rCtx.mxOwnerSelf.reset();
        return false;
    }

@@ -1149,9 +1150,11 @@ void Dialog::EndDialog( long nResult )
    mbInExecute = false;

    // Destroy ourselves (if we have a context with VclPtr owner)
    std::shared_ptr<weld::DialogController> xOwnerDialog = std::move(mpDialogImpl->maEndCtx.mxOwnerDialog);
    std::shared_ptr<weld::DialogController> xOwnerDialogController = std::move(mpDialogImpl->maEndCtx.mxOwnerDialogController);
    std::shared_ptr<weld::Dialog> xOwnerSelf = std::move(mpDialogImpl->maEndCtx.mxOwnerSelf);
    mpDialogImpl->maEndCtx.mxOwner.disposeAndClear();
    xOwnerDialog.reset();
    xOwnerDialogController.reset();
    xOwnerSelf.reset();
}

void Dialog::EndAllDialogs( vcl::Window const * pParent )
diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx
index b6cd35b..8392ab4 100644
--- a/vcl/unx/gtk3/gtk3gtkinst.cxx
+++ b/vcl/unx/gtk3/gtk3gtkinst.cxx
@@ -2367,6 +2367,8 @@ private:
    GtkDialog* m_pDialog;
    DialogRunner m_aDialogRun;
    std::shared_ptr<weld::DialogController> m_xDialogController;
    // Used to keep ourself alive during a runAsync(when doing runAsync without a DialogController)
    std::shared_ptr<GtkInstanceDialog> m_xRunAsyncSelf;
    std::function<void(sal_Int32)> m_aFunc;
    gulong m_nCloseSignalId;
    gulong m_nResponseSignalId;
@@ -2414,6 +2416,7 @@ private:
        m_aFunc(GtkToVcl(ret));
        m_aFunc = nullptr;
        m_xDialogController.reset();
        m_xRunAsyncSelf.reset();
    }

public:
@@ -2440,6 +2443,20 @@ public:
        return true;
    }

    virtual bool runAsync(const std::function<void(sal_Int32)>& func) override
    {
        assert(!m_nResponseSignalId);

        m_xRunAsyncSelf.reset(this);
        m_aFunc = func;

        show();

        m_nResponseSignalId = g_signal_connect(m_pDialog, "response", G_CALLBACK(signalAsyncResponse), this);

        return true;
    }

    bool has_click_handler(int nResponse);

    virtual int run() override