diff --git a/src/core/libraries/system/msgdialog_ui.cpp b/src/core/libraries/system/msgdialog_ui.cpp index 862f5a569..305263047 100644 --- a/src/core/libraries/system/msgdialog_ui.cpp +++ b/src/core/libraries/system/msgdialog_ui.cpp @@ -238,11 +238,21 @@ void MsgDialogUi::Finish(ButtonId buttonId, Result r) { } if (status) { *status = Status::FINISHED; + if (callback.has_value()) { + callback.value()(DialogResult{ + .result = r, + .buttonId = buttonId, + }); + } } state = nullptr; status = nullptr; result = nullptr; RemoveLayer(this); + if (self_destruct) { + self_destruct = false; + delete this; + } } void MsgDialogUi::Draw() { @@ -282,19 +292,24 @@ void MsgDialogUi::Draw() { first_render = false; } -DialogResult Libraries::MsgDialog::ShowMsgDialog(MsgDialogState p_state, bool block) { - static DialogResult result{}; - static Status status; - static MsgDialogUi dialog; - static MsgDialogState state; - dialog = MsgDialogUi{}; - status = Status::RUNNING; - state = std::move(p_state); - dialog = MsgDialogUi(&state, &status, &result); +void Libraries::MsgDialog::ShowMsgDialog( + MsgDialogState p_state, bool block, std::optional> callback) { + auto status = new Status{Status::RUNNING}; + auto state = new MsgDialogState{std::move(p_state)}; + auto dialog = new MsgDialogUi(state, status, nullptr); + bool running = true; + dialog->SetSelfDestruct(); + dialog->SetCallback([&, status, state, callback = std::move(callback)](auto result) { + running = false; + delete status; + delete state; + if (callback.has_value()) { + callback.value()(result); + } + }); if (block) { - while (status == Status::RUNNING) { + while (running) { std::this_thread::sleep_for(std::chrono::milliseconds(100)); } } - return result; } diff --git a/src/core/libraries/system/msgdialog_ui.h b/src/core/libraries/system/msgdialog_ui.h index d24ec067c..c56d6faa1 100644 --- a/src/core/libraries/system/msgdialog_ui.h +++ b/src/core/libraries/system/msgdialog_ui.h @@ -3,6 +3,7 @@ #pragma once +#include #include #include @@ -11,6 +12,8 @@ #include "core/libraries/system/commondialog.h" #include "imgui/imgui_layer.h" +#include + namespace Libraries::MsgDialog { using OrbisUserServiceUserId = s32; @@ -157,6 +160,10 @@ class MsgDialogUi final : public ImGui::Layer { CommonDialog::Status* status{}; DialogResult* result{}; + // HOST ONLY + bool self_destruct{false}; + std::optional> callback; + void DrawUser(); void DrawProgressBar(); void DrawSystemMessage(); @@ -169,13 +176,22 @@ public: MsgDialogUi(MsgDialogUi&& other) noexcept; MsgDialogUi& operator=(MsgDialogUi other); + void SetSelfDestruct() { + self_destruct = true; + } + + void SetCallback(std::function callback) { + this->callback = std::move(callback); + } + void Finish(ButtonId buttonId, CommonDialog::Result r = CommonDialog::Result::OK); void Draw() override; }; -// Utility function to show a message dialog -// !!! This function can block !!! -DialogResult ShowMsgDialog(MsgDialogState state, bool block = true); +// Utility function to show a message dialog from host code +// callback is called from the present thread +void ShowMsgDialog(MsgDialogState state, bool block = false, + std::optional> callback = std::nullopt); }; // namespace Libraries::MsgDialog \ No newline at end of file