diff --git a/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp b/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp index d81f56b2ae..6c4e72f48e 100644 --- a/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp +++ b/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp @@ -9,6 +9,8 @@ #include "cellOskDialog.h" #include "cellMsgDialog.h" +#include "util/init_mutex.hpp" + LOG_CHANNEL(cellOskDialog); template<> @@ -32,36 +34,56 @@ OskDialogBase::~OskDialogBase() { } -std::shared_ptr _get_osk_dialog(bool always = false) +struct osk_info { - if (auto manager = g_fxo->get()) - { - // NOTE: Osk lifetime is managed by fxm, not display manager - // Visibility is still managed by display manager - auto osk = fxm::get(); - if (always) - { - if (!osk) - { - // Create if does not exist - osk = fxm::make(); - } + std::shared_ptr dlg; - // Attach to display manager forcefully - osk = manager->add(osk); + atomic_t use_separate_windows = false; + + atomic_t osk_continuous_mode = CELL_OSKDIALOG_CONTINUOUS_MODE_NONE; + + atomic_t> osk_confirm_callback{}; + + stx::init_mutex init; +}; + +// TODO: don't use this function +std::shared_ptr _get_osk_dialog(bool create = false) +{ + const auto osk = g_fxo->get(); + + if (create) + { + const auto init = osk->init.init(); + + if (!init) + { + return nullptr; } - return osk; + if (auto manager = g_fxo->get()) + { + auto dlg = std::make_shared(); + + osk->dlg = manager->add(dlg); + } + else + { + osk->dlg = Emu.GetCallbacks().get_osk_dialog(); + } + + return osk->dlg; } else { - auto osk = fxm::get(); - if (always && !osk) + const auto init = osk->init.access(); + + if (!init) { - return fxm::import(Emu.GetCallbacks().get_osk_dialog); + return nullptr; } - return osk; + return osk->dlg; } } @@ -139,7 +161,7 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr dia if (accepted) { - if (osk->osk_confirm_callback) + if (auto ccb = g_fxo->get()->osk_confirm_callback.exchange({})) { vm::ptr string_to_send = vm::cast(vm::alloc(CELL_OSKDIALOG_STRING_SIZE * 2, vm::main)); atomic_t done = false; @@ -154,7 +176,7 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr dia sysutil_register_cb([&, length = i](ppu_thread& cb_ppu) -> s32 { - return_value = osk->osk_confirm_callback(cb_ppu, string_to_send, (s32)length); + return_value = ccb(cb_ppu, string_to_send, (s32)length); cellOskDialog.warning("osk_confirm_callback return_value=%d", return_value); for (u32 i = 0; i < CELL_OSKDIALOG_STRING_SIZE - 1; i++) @@ -171,12 +193,9 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr dia { std::this_thread::yield(); } - - // reset this here (just to make sure it's null) - osk->osk_confirm_callback = vm::null; } - if (osk->use_seperate_windows.load() && osk->osk_text[0] == 0) + if (g_fxo->get()->use_separate_windows.load() && osk->osk_text[0] == 0) { cellOskDialog.warning("cellOskDialogLoadAsync: input result is CELL_OSKDIALOG_INPUT_FIELD_RESULT_NO_INPUT_TEXT"); osk->osk_input_result = CELL_OSKDIALOG_INPUT_FIELD_RESULT_NO_INPUT_TEXT; @@ -192,7 +211,7 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr dia } // Send OSK status - if (osk->use_seperate_windows.load() && (osk->osk_continuous_mode.load() != CELL_OSKDIALOG_CONTINUOUS_MODE_NONE)) + if (g_fxo->get()->use_separate_windows.load() && (g_fxo->get()->osk_continuous_mode.load() != CELL_OSKDIALOG_CONTINUOUS_MODE_NONE)) { if (accepted) { @@ -215,7 +234,7 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr dia { const auto osk = wptr.lock(); - if (osk->use_seperate_windows.load()) + if (g_fxo->get()->use_separate_windows.load()) { sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_INPUT_ENTERED, 0); } @@ -302,7 +321,12 @@ error_code getText(vm::ptr OutputInfo, bool is if (is_unload) { // Unload should be called last, so remove the dialog here - fxm::remove(); + if (const auto reset_lock = g_fxo->get()->init.reset()) + { + // TODO + g_fxo->get()->dlg.reset(); + } + sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_UNLOADED, 0); } @@ -394,10 +418,10 @@ error_code cellOskDialogSetSeparateWindowOption(vm::ptrget(); true) { - osk->use_seperate_windows = true; - osk->osk_continuous_mode = (CellOskDialogContinuousMode)(u32)windowOption->continuousMode; + osk->use_separate_windows = true; + osk->osk_continuous_mode = static_cast(+windowOption->continuousMode); } return CELL_OK; @@ -525,7 +549,7 @@ error_code cellOskDialogExtRegisterConfirmWordFilterCallback(vm::ptrget(); true) { osk->osk_confirm_callback = pCallback; } diff --git a/rpcs3/Emu/Cell/Modules/cellOskDialog.h b/rpcs3/Emu/Cell/Modules/cellOskDialog.h index d13706810c..f8f0ff61d6 100644 --- a/rpcs3/Emu/Cell/Modules/cellOskDialog.h +++ b/rpcs3/Emu/Cell/Modules/cellOskDialog.h @@ -251,12 +251,8 @@ public: std::function on_osk_input_entered; atomic_t state{ OskDialogState::Close }; - atomic_t use_seperate_windows{ false }; - atomic_t osk_continuous_mode{ CellOskDialogContinuousMode::CELL_OSKDIALOG_CONTINUOUS_MODE_NONE }; atomic_t osk_input_result{ CellOskDialogInputFieldResult::CELL_OSKDIALOG_INPUT_FIELD_RESULT_OK }; char16_t osk_text[CELL_OSKDIALOG_STRING_SIZE]{}; char16_t osk_text_old[CELL_OSKDIALOG_STRING_SIZE]{}; - - vm::ptr osk_confirm_callback{ vm::null }; }; diff --git a/rpcs3/Emu/RSX/Overlays/overlay_osk.cpp b/rpcs3/Emu/RSX/Overlays/overlay_osk.cpp index 3f6fd5550c..d3e954f253 100644 --- a/rpcs3/Emu/RSX/Overlays/overlay_osk.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlay_osk.cpp @@ -569,7 +569,7 @@ namespace rsx } // Language specific implementations - void osk_enUS::Create(const std::string& title, const std::u16string& message, char16_t* init_text, u32 charlimit, u32 options) + void osk_latin::Create(const std::string& title, const std::u16string& message, char16_t* init_text, u32 charlimit, u32 options) { state = OskDialogState::Open; flags = options; diff --git a/rpcs3/Emu/RSX/Overlays/overlays.h b/rpcs3/Emu/RSX/Overlays/overlays.h index ec70df4690..99d6184c4d 100644 --- a/rpcs3/Emu/RSX/Overlays/overlays.h +++ b/rpcs3/Emu/RSX/Overlays/overlays.h @@ -482,7 +482,7 @@ namespace rsx compiled_resource get_compiled() override; }; - struct osk_enUS : osk_dialog + struct osk_latin : osk_dialog { using osk_dialog::osk_dialog;