--- a/ui/winui/toolkit.cpp Sun Jan 28 17:10:30 2024 +0100 +++ b/ui/winui/toolkit.cpp Sun Jan 28 19:33:56 2024 +0100 @@ -43,6 +43,8 @@ #include "App.xaml.h" +#include <thread> + using namespace winrt; using namespace Microsoft::UI::Xaml; using namespace Microsoft::UI::Xaml::Controls; @@ -50,6 +52,7 @@ using namespace Microsoft::UI::Xaml::Markup; using namespace Windows::UI::Xaml::Interop; using namespace winrt::Windows::Foundation; +using namespace Windows::UI::Core; static const char* application_name; @@ -69,7 +72,11 @@ static UiObject* active_window; +static winrt::Microsoft::UI::Dispatching::DispatcherQueue uiDispatcherQueue = { nullptr }; + void ui_app_run_startup() { + uiDispatcherQueue = winrt::Microsoft::UI::Dispatching::DispatcherQueue::GetForCurrentThread(); + if (startup_func) { startup_func(NULL, startup_data); } @@ -233,3 +240,58 @@ } +static void ui_job_finished(UiJob *job) { + UiEvent event; + event.obj = job->obj; + event.window = job->obj->window; + event.document = job->obj->ctx->document; + event.intval = 0; + event.eventdata = NULL; + job->finish_callback(&event, job->finish_data); +} + +static void ui_job_thread(UiJob* job) { + if (!job->job_func(job->job_data)) { + bool isQueued = uiDispatcherQueue.TryEnqueue([job]() + { + UiEvent event; + event.obj = job->obj; + event.window = job->obj->window; + event.document = job->obj->ctx->document; + event.intval = 0; + event.eventdata = NULL; + job->finish_callback(&event, job->finish_data); + delete job; + }); + if (!isQueued) { + // TODO: error or try again? + exit(-1); + } + } + else { + delete job; + } +} + +UIEXPORT void ui_job(UiObject* obj, ui_threadfunc tf, void* td, ui_callback f, void* fd) { + UiJob* job = new UiJob; + job->obj = obj; + job->job_func = tf; + job->job_data = td; + job->finish_callback = f; + job->finish_data = fd; + + std::thread jobThread(ui_job_thread, job); + jobThread.detach(); +} + +UIEXPORT void ui_call_mainthread(ui_threadfunc tf, void* td) { + bool isQueued = uiDispatcherQueue.TryEnqueue([tf, td]() + { + (void)tf(td); + }); + if (!isQueued) { + // TODO: error or try again? + exit(-1); + } +}