diff --git a/aegisub/src/auto4_base.cpp b/aegisub/src/auto4_base.cpp index 1d0452408..4e04a368a 100644 --- a/aegisub/src/auto4_base.cpp +++ b/aegisub/src/auto4_base.cpp @@ -223,9 +223,6 @@ namespace Automation4 { } // ProgressSink - wxDEFINE_EVENT(EVT_SHOW_DIALOG, wxThreadEvent); - wxDEFINE_EVENT(EVT_SHOW_SCRIPT_DIALOG, wxThreadEvent); - ProgressSink::ProgressSink(agi::ProgressSink *impl, BackgroundScriptRunner *bsr) : impl(impl) , bsr(bsr) @@ -235,74 +232,35 @@ namespace Automation4 { void ProgressSink::ShowDialog(ScriptDialog *config_dialog) { - wxSemaphore sema(0, 1); - wxThreadEvent *evt = new wxThreadEvent(EVT_SHOW_SCRIPT_DIALOG); - evt->SetPayload(std::make_pair(config_dialog, &sema)); - bsr->QueueEvent(evt); - sema.Wait(); + InvokeOnMainThread([=] { + wxDialog w; // container dialog box + w.SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY); + w.Create(bsr->GetParentWindow(), -1, bsr->GetTitle()); + wxBoxSizer *s = new wxBoxSizer(wxHORIZONTAL); // sizer for putting contents in + wxWindow *ww = config_dialog->CreateWindow(&w); // generate actual dialog contents + s->Add(ww, 0, wxALL, 5); // add contents to dialog + w.SetSizerAndFit(s); + w.CenterOnParent(); + w.ShowModal(); + }); } int ProgressSink::ShowDialog(wxDialog *dialog) { int ret = 0; - wxSemaphore sema(0, 1); - wxThreadEvent *evt = new wxThreadEvent(EVT_SHOW_DIALOG); - evt->SetPayload(std::make_tuple(dialog, &sema, &ret)); - bsr->QueueEvent(evt); - sema.Wait(); + InvokeOnMainThread([&] { ret = dialog->ShowModal(); }); return ret; } BackgroundScriptRunner::BackgroundScriptRunner(wxWindow *parent, wxString const& title) : impl(new DialogProgress(parent, title)) { - impl->Bind(EVT_SHOW_DIALOG, &BackgroundScriptRunner::OnDialog, this); - impl->Bind(EVT_SHOW_SCRIPT_DIALOG, &BackgroundScriptRunner::OnScriptDialog, this); } BackgroundScriptRunner::~BackgroundScriptRunner() { } - void BackgroundScriptRunner::OnScriptDialog(wxThreadEvent &evt) - { - std::pair payload = evt.GetPayload >(); - - wxDialog w; // container dialog box - w.SetExtraStyle(wxWS_EX_VALIDATE_RECURSIVELY); - w.Create(impl.get(), -1, impl->GetTitle()); - wxBoxSizer *s = new wxBoxSizer(wxHORIZONTAL); // sizer for putting contents in - wxWindow *ww = payload.first->CreateWindow(&w); // generate actual dialog contents - s->Add(ww, 0, wxALL, 5); // add contents to dialog - w.SetSizerAndFit(s); - w.CenterOnParent(); - w.ShowModal(); - - // Tell the calling thread it can wake up now - payload.second->Post(); - } - - void BackgroundScriptRunner::OnDialog(wxThreadEvent &evt) - { - using namespace std; - tuple payload = evt.GetPayload >(); - *get<2>(payload) = get<0>(payload)->ShowModal(); - get<1>(payload)->Post(); - } - - void BackgroundScriptRunner::QueueEvent(wxEvent *evt) - { - wxQueueEvent(impl.get(), evt); - } - - // Convert a function taking an Automation4::ProgressSink to one taking an - // agi::ProgressSink so that we can pass it to an agi::BackgroundWorker - static void progress_sink_wrapper(std::function task, agi::ProgressSink *ps, BackgroundScriptRunner *bsr) - { - ProgressSink aps(ps, bsr); - task(&aps); - } - void BackgroundScriptRunner::Run(std::function task) { int prio = OPT_GET("Automation/Thread Priority")->GetInt(); @@ -311,7 +269,10 @@ namespace Automation4 { else if (prio == 2) prio = 10; // lowest else prio = 50; // fallback normal - impl->Run(bind(progress_sink_wrapper, task, std::placeholders::_1, this), prio); + impl->Run([&](agi::ProgressSink *ps) { + ProgressSink aps(ps, this); + task(&aps); + }, prio); } wxWindow *BackgroundScriptRunner::GetParentWindow() const @@ -319,6 +280,11 @@ namespace Automation4 { return impl.get(); } + wxString BackgroundScriptRunner::GetTitle() const + { + return impl->GetTitle(); + } + // Script Script::Script(wxString const& filename) : filename(filename) diff --git a/aegisub/src/auto4_base.h b/aegisub/src/auto4_base.h index 37d3221d3..8565d83af 100644 --- a/aegisub/src/auto4_base.h +++ b/aegisub/src/auto4_base.h @@ -124,11 +124,9 @@ namespace Automation4 { class BackgroundScriptRunner { agi::scoped_ptr impl; - void OnDialog(wxThreadEvent &evt); - void OnScriptDialog(wxThreadEvent &evt); public: - void QueueEvent(wxEvent *evt); wxWindow *GetParentWindow() const; + wxString GetTitle() const; void Run(std::function task); diff --git a/aegisub/src/main.cpp b/aegisub/src/main.cpp index f22e7c46f..9615e515d 100644 --- a/aegisub/src/main.cpp +++ b/aegisub/src/main.cpp @@ -144,6 +144,10 @@ bool AegisubApp::OnInit() { SetAppName("aegisub"); #endif + Bind(EVT_CALL_THUNK, [](wxThreadEvent &evt) { + evt.GetPayload>()(); + }); + // logging. agi::log::log = new agi::log::LogSink; diff --git a/aegisub/src/utils.cpp b/aegisub/src/utils.cpp index bca002c2d..eb4be3aea 100644 --- a/aegisub/src/utils.cpp +++ b/aegisub/src/utils.cpp @@ -58,6 +58,8 @@ #include "compat.h" #include "main.h" +wxDEFINE_EVENT(EVT_CALL_THUNK, wxThreadEvent); + wxString MakeRelativePath(wxString _path, wxString reference) { if (_path.empty() || _path[0] == '?') return _path; wxFileName path(_path); diff --git a/aegisub/src/utils.h b/aegisub/src/utils.h index caa03dc42..62b67b656 100644 --- a/aegisub/src/utils.h +++ b/aegisub/src/utils.h @@ -39,9 +39,11 @@ #include #include +#include #include #include +#include #include #include #endif @@ -182,3 +184,19 @@ struct cast { return dynamic_cast(&in); } }; + +wxDECLARE_EVENT(EVT_CALL_THUNK, wxThreadEvent); + +template +void InvokeOnMainThreadAsync(Function const& f) { + wxThreadEvent *evt = new wxThreadEvent(EVT_CALL_THUNK); + evt->SetPayload>(f); + wxTheApp->QueueEvent(evt); +} + +template +void InvokeOnMainThread(Function const& f) { + wxSemaphore sema(0, 1); + InvokeOnMainThreadAsync([&] { f(); sema.Post(); }); + sema.Wait(); +}