include/vcl/abstdlg.hxx | 3 + include/vcl/dialog.hxx | 2 - include/vcl/weld.hxx | 34 +++++++++++++++++ sw/source/uibase/docvw/edtwin.cxx | 5 +- vcl/source/app/salvtables.cxx | 23 ++++++++++++ vcl/source/window/dialog.cxx | 3 + vcl/unx/gtk3/gtk3gtkinst.cxx | 72 +++++++++++++++++++++++++++++++------- 7 files changed, 125 insertions(+), 17 deletions(-)
New commits: commit 0b573eac85b3100eb8d40dcaf25c510f50cfd62f Author: Pranav Kant <pran...@collabora.co.uk> Date: Thu Mar 1 20:15:58 2018 +0530 lokdialog: run async for weld dialogs Change-Id: Ieb06beada435bc47a39295acb5ea2dcef10ca454 Reviewed-on: https://gerrit.libreoffice.org/50874 Tested-by: Jenkins <c...@libreoffice.org> Reviewed-by: Caolán McNamara <caol...@redhat.com> Tested-by: Caolán McNamara <caol...@redhat.com> Reviewed-by: pranavk <pran...@collabora.co.uk> Tested-by: pranavk <pran...@collabora.co.uk> diff --git a/include/vcl/abstdlg.hxx b/include/vcl/abstdlg.hxx index 542930084e37..af676785b295 100644 --- a/include/vcl/abstdlg.hxx +++ b/include/vcl/abstdlg.hxx @@ -26,10 +26,12 @@ #include <vcl/vclreferencebase.hxx> #include <vector> #include <functional> +#include <memory> namespace vcl { class Window; } class Dialog; class Bitmap; +namespace weld { class DialogController; } /** * Some things multiple-inherit from VclAbstractDialog and OutputDevice, @@ -45,6 +47,7 @@ public: struct AsyncContext { VclPtr<VclReferenceBase> mxOwner; + std::shared_ptr<weld::DialogController> mxOwnerDialog; std::function<void(sal_Int32)> maEndDialogFn; bool isSet() { return !!maEndDialogFn; } }; diff --git a/include/vcl/dialog.hxx b/include/vcl/dialog.hxx index 243d071b101f..0b98901e32bb 100644 --- a/include/vcl/dialog.hxx +++ b/include/vcl/dialog.hxx @@ -149,7 +149,7 @@ private: public: // FIXME: Need to remove old StartExecuteModal in favour of this one. - /// Returns true of the dialog successfully starts + /// Returns true if the dialog successfully starts bool StartExecuteAsync(const std::function<void(sal_Int32)> &rEndDialogFn) { VclAbstractDialog::AsyncContext aCtx; diff --git a/include/vcl/weld.hxx b/include/vcl/weld.hxx index b861b848e84c..ff3a1e8c346e 100644 --- a/include/vcl/weld.hxx +++ b/include/vcl/weld.hxx @@ -20,6 +20,7 @@ namespace weld { class Container; +class DialogController; class VCL_DLLPUBLIC Widget { @@ -120,6 +121,12 @@ public: class VCL_DLLPUBLIC Dialog : virtual public Window { +private: + friend DialogController; + virtual bool runAsync(std::shared_ptr<DialogController>, + const std::function<void(sal_Int32)>& func) + = 0; + public: virtual int run() = 0; virtual void response(int response) = 0; @@ -534,8 +541,33 @@ public: virtual DrawingArea* weld_drawing_area(const OString& id, bool bTakeOwnership = false) = 0; virtual ~Builder() {} }; -} +class VCL_DLLPUBLIC DialogController +{ +private: + virtual Dialog* getDialog() = 0; + +public: + short run() { return getDialog()->run(); } + static bool runAsync(const std::shared_ptr<DialogController>& rController, + const std::function<void(sal_Int32)>&); + virtual ~DialogController() {} +}; + +class VCL_DLLPUBLIC GenericDialogController : public DialogController +{ +private: + virtual Dialog* getDialog() override { return m_xDialog.get(); } + +protected: + std::unique_ptr<weld::Builder> m_xBuilder; + std::unique_ptr<weld::Dialog> m_xDialog; + +public: + GenericDialogController(weld::Widget* pParent, const OUString& rUIFile, + const OString& rDialogId); +}; +} #endif /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/sw/source/uibase/docvw/edtwin.cxx b/sw/source/uibase/docvw/edtwin.cxx index 8c33ce4e5ba3..a6334cd57e60 100644 --- a/sw/source/uibase/docvw/edtwin.cxx +++ b/sw/source/uibase/docvw/edtwin.cxx @@ -2474,9 +2474,8 @@ KEYINPUT_CHECKTABLE_INSDEL: } else { - std::unique_ptr<weld::Builder> xBuilder(Application::CreateBuilder(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui")); - std::unique_ptr<weld::MessageDialog> xInfo(xBuilder->weld_message_dialog("InfoReadonlyDialog")); - xInfo->run(); + auto xInfo(std::make_shared<weld::GenericDialogController>(GetFrameWeld(), "modules/swriter/ui/inforeadonlydialog.ui", "InfoReadonlyDialog")); + weld::DialogController::runAsync(xInfo, [](int) {}); eKeyState = SwKeyState::End; } break; diff --git a/vcl/source/app/salvtables.cxx b/vcl/source/app/salvtables.cxx index bb304d2dc811..3f95a7589849 100644 --- a/vcl/source/app/salvtables.cxx +++ b/vcl/source/app/salvtables.cxx @@ -17,6 +17,7 @@ * the License at http://www.apache.org/licenses/LICENSE-2.0 . */ +#include <comphelper/lok.hxx> #include <salframe.hxx> #include <salinst.hxx> #include <salvd.hxx> @@ -430,6 +431,14 @@ 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.maEndDialogFn = rEndDialogFn; + return m_xDialog->StartExecuteAsync(aCtx); + } + virtual int run() override { VclButtonBox* pActionArea = m_xDialog->get_action_area(); @@ -1458,4 +1467,18 @@ weld::Window* SalFrame::GetFrameWeld() const return m_xFrameWeld.get(); } +namespace weld +{ + bool DialogController::runAsync(const std::shared_ptr<DialogController>& rController, const std::function<void(sal_Int32)>& func) + { + return rController->getDialog()->runAsync(rController, func); + } + + GenericDialogController::GenericDialogController(weld::Widget* pParent, const OUString &rUIFile, const OString& rDialogId) + : m_xBuilder(Application::CreateBuilder(pParent, rUIFile)) + , m_xDialog(m_xBuilder->weld_dialog(rDialogId)) + { + } +} + /* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/vcl/source/window/dialog.cxx b/vcl/source/window/dialog.cxx index 75d31d1f17b4..11670c6459b6 100644 --- a/vcl/source/window/dialog.cxx +++ b/vcl/source/window/dialog.cxx @@ -1036,6 +1036,7 @@ bool Dialog::StartExecuteAsync( VclAbstractDialog::AsyncContext &rCtx ) if ( !ImplStartExecuteModal() ) { rCtx.mxOwner.disposeAndClear(); + rCtx.mxOwnerDialog.reset(); return false; } @@ -1103,7 +1104,9 @@ 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); mpDialogImpl->maEndCtx.mxOwner.disposeAndClear(); + xOwnerDialog.reset(); } long Dialog::GetResult() const diff --git a/vcl/unx/gtk3/gtk3gtkinst.cxx b/vcl/unx/gtk3/gtk3gtkinst.cxx index 4a8912594e45..031f012c8152 100644 --- a/vcl/unx/gtk3/gtk3gtkinst.cxx +++ b/vcl/unx/gtk3/gtk3gtkinst.cxx @@ -1499,21 +1499,77 @@ class GtkInstanceDialog : public GtkInstanceWindow, public virtual weld::Dialog { private: GtkDialog* m_pDialog; + std::shared_ptr<weld::DialogController> m_xDialogController; + std::function<void(sal_Int32)> m_aFunc; gulong m_nCloseSignalId; + gulong m_nResponseSignalId; - static void signalClose(GtkWidget *, gpointer widget) + static void signalClose(GtkWidget*, gpointer widget) { GtkInstanceDialog* pThis = static_cast<GtkInstanceDialog*>(widget); pThis->response(RET_CANCEL); } + + static void signalAsyncResponse(GtkWidget*, gint ret, gpointer widget) + { + GtkInstanceDialog* pThis = static_cast<GtkInstanceDialog*>(widget); + pThis->asyncresponse(ret); + } + + static int GtkToVcl(int ret) + { + if (ret == GTK_RESPONSE_OK) + ret = RET_OK; + else if (ret == GTK_RESPONSE_CANCEL) + ret = RET_CANCEL; + else if (ret == GTK_RESPONSE_CLOSE) + ret = RET_CLOSE; + else if (ret == GTK_RESPONSE_YES) + ret = RET_YES; + else if (ret == GTK_RESPONSE_NO) + ret = RET_NO; + return ret; + } + + void asyncresponse(gint ret) + { + if (ret == GTK_RESPONSE_HELP) + { + help(); + return; + } + + hide(); + m_aFunc(GtkToVcl(ret)); + m_xDialogController.reset(); + } public: GtkInstanceDialog(GtkDialog* pDialog, bool bTakeOwnership) : GtkInstanceWindow(GTK_WINDOW(pDialog), bTakeOwnership) , m_pDialog(pDialog) , m_nCloseSignalId(g_signal_connect(m_pDialog, "close", G_CALLBACK(signalClose), this)) + , m_nResponseSignalId(0) { } + virtual bool runAsync(std::shared_ptr<weld::DialogController> rDialogController, const std::function<void(sal_Int32)>& func) override + { + assert(!m_nResponseSignalId); + + m_xDialogController = rDialogController; + m_aFunc = func; + + if (!gtk_widget_get_visible(m_pWidget)) + { + sort_native_button_order(GTK_BOX(gtk_dialog_get_action_area(m_pDialog))); + gtk_widget_show(m_pWidget); + } + + m_nResponseSignalId = g_signal_connect(m_pDialog, "response", G_CALLBACK(signalAsyncResponse), this); + + return true; + } + virtual int run() override { sort_native_button_order(GTK_BOX(gtk_dialog_get_action_area(m_pDialog))); @@ -1526,20 +1582,10 @@ public: help(); continue; } - else if (ret == GTK_RESPONSE_OK) - ret = RET_OK; - else if (ret == GTK_RESPONSE_CANCEL) - ret = RET_CANCEL; - else if (ret == GTK_RESPONSE_CLOSE) - ret = RET_CLOSE; - else if (ret == GTK_RESPONSE_YES) - ret = RET_YES; - else if (ret == GTK_RESPONSE_NO) - ret = RET_NO; break; } hide(); - return ret; + return GtkToVcl(ret); } static int VclToGtk(int nResponse) @@ -1577,6 +1623,8 @@ public: virtual ~GtkInstanceDialog() override { g_signal_handler_disconnect(m_pDialog, m_nCloseSignalId); + if (m_nResponseSignalId) + g_signal_handler_disconnect(m_pDialog, m_nResponseSignalId); } }; _______________________________________________ Libreoffice-commits mailing list libreoffice-comm...@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits