diff --git a/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp b/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp index 183a508247..8184d6db56 100644 --- a/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp @@ -87,7 +87,12 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr msgString, vm::ptr()) { - manager->create()->show(msgString.get_ptr(), _type, [callback, userData](s32 status) + if (manager->get()) + { + return CELL_SYSUTIL_ERROR_BUSY; + } + + const auto res = manager->create()->show(msgString.get_ptr(), _type, [callback, userData](s32 status) { if (callback) { @@ -99,7 +104,7 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr msgString, vm::ptr(Emu.GetCallbacks().get_msg_dialog); @@ -128,8 +133,12 @@ s32 cellMsgDialogOpen2(u32 type, vm::cptr msgString, vm::ptr(); } + + pad::SetIntercepted(false); }; + pad::SetIntercepted(true); + atomic_t result(false); // Run asynchronously in GUI thread diff --git a/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp b/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp index 8de3500c6c..00167e1034 100644 --- a/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp +++ b/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp @@ -1,6 +1,8 @@ #include "stdafx.h" -#include "Emu/Cell/PPUModule.h" #include "Emu/System.h" +#include "Emu/IdManager.h" +#include "Emu/Cell/PPUModule.h" +#include "pad_thread.h" #include "cellSysutil.h" #include "cellOskDialog.h" @@ -22,14 +24,28 @@ s32 cellOskDialogLoadAsync(u32 container, vm::ptr dialogPara for (u32 i = 0; (i < maxLength) && (inputFieldInfo->init_text[i] != 0); i++) s_osk_text[i] = inputFieldInfo->init_text[i]; - const auto osk = Emu.GetCallbacks().get_msg_dialog(); + const auto osk = fxm::import(Emu.GetCallbacks().get_msg_dialog); + + if (!osk) + { + return CELL_SYSUTIL_ERROR_BUSY; + } + bool result = false; - osk->on_close = [&](s32 status) + osk->on_close = [wptr = std::weak_ptr(osk)](s32 status) { + const auto osk = wptr.lock(); + + if (osk && osk->state.compare_and_swap_test(MsgDialogState::Open, MsgDialogState::Close)) + { + fxm::remove(); + } + if (status != CELL_MSGDIALOG_BUTTON_OK) sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_INPUT_CANCELED, 0); sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_FINISHED, 0); - result = true; + + pad::SetIntercepted(false); }; osk->on_osk_input_entered = [&]() @@ -37,9 +53,12 @@ s32 cellOskDialogLoadAsync(u32 container, vm::ptr dialogPara sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_INPUT_ENTERED, 0); }; + pad::SetIntercepted(true); + Emu.CallAfter([&]() { osk->CreateOsk("On Screen Keyboard", s_osk_text, maxLength); + result = true; }); sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_LOADED, 0); @@ -78,6 +97,21 @@ s32 cellOskDialogGetSize(vm::ptr width, vm::ptr height, vm::ptr(); + + if (!dlg) + { + return CELL_MSGDIALOG_ERROR_DIALOG_NOT_OPENED; + } + + if (!dlg->state.compare_and_swap_test(MsgDialogState::Open, MsgDialogState::Abort)) + { + return CELL_SYSUTIL_ERROR_BUSY; + } + + verify(HERE), fxm::remove(); + sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_FINISHED, 0); return CELL_OK; } @@ -133,7 +167,7 @@ s32 cellOskDialogSetLayoutMode(s32 layoutMode) s32 cellOskDialogGetInputText(vm::ptr OutputInfo) { cellOskDialog.warning("cellOskDialogGetInputText(OutputInfo=*0x%x)", OutputInfo); - return cellOskDialogUnloadAsync(OutputInfo); //Same but for use with cellOskDialogSetSeparateWindowOption(). TODO. + return cellOskDialogUnloadAsync(OutputInfo); // Same but for use with cellOskDialogSetSeparateWindowOption(). TODO. } s32 cellOskDialogExtInputDeviceUnlock() @@ -220,9 +254,9 @@ s32 cellOskDialogExtSetPointerEnable(b8 enable) return CELL_OK; } -s32 cellOskDialogExtUpdatePointerDisplayPos() +s32 cellOskDialogExtUpdatePointerDisplayPos(/*const CellOskDialogPoint pos*/) { - cellOskDialog.todo("cellOskDialogExtUpdatePointerDisplayPos"); // Missing arguments + cellOskDialog.todo("cellOskDialogExtUpdatePointerDisplayPos(posX=%f, posY=%f)"/*, pos.x, pos.y*/); return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/cellOskDialog.h b/rpcs3/Emu/Cell/Modules/cellOskDialog.h index 9fc7555bfa..71ec22dd6e 100644 --- a/rpcs3/Emu/Cell/Modules/cellOskDialog.h +++ b/rpcs3/Emu/Cell/Modules/cellOskDialog.h @@ -2,7 +2,7 @@ -//error codes +// error codes enum { CELL_OSKDIALOG_ERROR_IME_ALREADY_IN_USE = 0x8002b501, @@ -11,7 +11,7 @@ enum CELL_OSKDIALOG_ERROR_PARAM = 0x8002b504, }; -//OSK status for the callback +// OSK status for the callback enum { CELL_SYSUTIL_OSKDIALOG_LOADED = 0x0502, @@ -94,7 +94,7 @@ enum CellOskDialogType enum { - CELL_OSKDIALOG_STRING_SIZE = 512, //Theroretical maxium for osk input, games can specify a lower limit + CELL_OSKDIALOG_STRING_SIZE = 512, // Theroretical maximum for osk input, games can specify a lower limit }; struct CellOskDialogInputFieldInfo @@ -118,10 +118,10 @@ struct CellOskDialogParam be_t prohibitFlgs; }; -//Actual input data +// Actual input data struct CellOskDialogCallbackReturnParam { - be_t result; //CellOskDialogInputFieldResult + be_t result; // CellOskDialogInputFieldResult be_t numCharsResultString; vm::bptr pResultString; }; diff --git a/rpcs3/Emu/Io/PadHandler.h b/rpcs3/Emu/Io/PadHandler.h index 59b5f3feae..47589bf302 100644 --- a/rpcs3/Emu/Io/PadHandler.h +++ b/rpcs3/Emu/Io/PadHandler.h @@ -10,6 +10,11 @@ // TODO: HLE info (constants, structs, etc.) should not be available here +enum SystemInfo +{ + CELL_PAD_INFO_INTERCEPTED = 0x00000001 +}; + enum PortStatus { CELL_PAD_STATUS_DISCONNECTED = 0x00000000, diff --git a/rpcs3/Emu/RSX/Overlays/overlays.cpp b/rpcs3/Emu/RSX/Overlays/overlays.cpp index deae481b5f..c8da1dd559 100644 --- a/rpcs3/Emu/RSX/Overlays/overlays.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlays.cpp @@ -9,6 +9,134 @@ namespace rsx // Singleton instance declaration fontmgr* fontmgr::m_instance = nullptr; + s32 user_interface::run_input_loop() + { + std::array timestamp; + timestamp.fill(std::chrono::steady_clock::now()); + + std::array, CELL_PAD_MAX_PORT_NUM> button_state; + for (auto& state : button_state) + { + state.fill(true); + } + + input_timer.Start(); + + { + std::lock_guard lock(pad::g_pad_mutex); + const auto handler = pad::get_current_handler(); + handler->SetIntercepted(true); + } + + while (!exit) + { + if (Emu.IsStopped()) + return selection_code::canceled; + + std::this_thread::sleep_for(1ms); + + std::lock_guard lock(pad::g_pad_mutex); + + const auto handler = pad::get_current_handler(); + + const PadInfo& rinfo = handler->GetInfo(); + + if (Emu.IsPaused() || !rinfo.now_connect) + { + continue; + } + + int pad_index = -1; + for (const auto &pad : handler->GetPads()) + { + if (++pad_index >= CELL_PAD_MAX_PORT_NUM) + { + LOG_FATAL(RSX, "The native overlay cannot handle more than 7 pads! Current number of pads: %d", pad_index + 1); + continue; + } + + for (auto &button : pad->m_buttons) + { + u8 button_id = 255; + if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL1) + { + switch (button.m_outKeyCode) + { + case CELL_PAD_CTRL_LEFT: + button_id = pad_button::dpad_left; + break; + case CELL_PAD_CTRL_RIGHT: + button_id = pad_button::dpad_right; + break; + case CELL_PAD_CTRL_DOWN: + button_id = pad_button::dpad_down; + break; + case CELL_PAD_CTRL_UP: + button_id = pad_button::dpad_up; + break; + } + } + else if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL2) + { + switch (button.m_outKeyCode) + { + case CELL_PAD_CTRL_TRIANGLE: + button_id = pad_button::triangle; + break; + case CELL_PAD_CTRL_CIRCLE: + button_id = g_cfg.sys.enter_button_assignment == enter_button_assign::circle ? pad_button::cross : pad_button::circle; + break; + case CELL_PAD_CTRL_SQUARE: + button_id = pad_button::square; + break; + case CELL_PAD_CTRL_CROSS: + button_id = g_cfg.sys.enter_button_assignment == enter_button_assign::circle ? pad_button::circle : pad_button::cross; + break; + } + } + + if (button_id < 255) + { + if (button.m_pressed) + { + if (button_id < 4) // d-pad button + { + if (!button_state[pad_index][button_id] || input_timer.GetMsSince(timestamp[pad_index]) > 400) + { + // d-pad button was not pressed, or was pressed more than 400ms ago + timestamp[pad_index] = std::chrono::steady_clock::now(); + on_button_pressed(static_cast(button_id)); + } + } + else if (!button_state[pad_index][button_id]) + { + // button was not pressed + on_button_pressed(static_cast(button_id)); + } + } + + button_state[pad_index][button_id] = button.m_pressed; + } + + if (button.m_flush) + { + button.m_pressed = false; + button.m_flush = false; + button.m_value = 0; + } + + if (exit) + return 0; + } + } + + refresh(); + } + + // Unreachable + return 0; + } + void user_interface::close() { // Force unload @@ -24,6 +152,12 @@ namespace rsx manager->remove(uid); } + { + std::lock_guard lock(pad::g_pad_mutex); + const auto handler = pad::get_current_handler(); + handler->SetIntercepted(false); + } + if (on_close) on_close(return_code); } diff --git a/rpcs3/Emu/RSX/Overlays/overlays.h b/rpcs3/Emu/RSX/Overlays/overlays.h index 2e5640bf59..96757d7c35 100644 --- a/rpcs3/Emu/RSX/Overlays/overlays.h +++ b/rpcs3/Emu/RSX/Overlays/overlays.h @@ -80,127 +80,7 @@ namespace rsx void close(); - s32 run_input_loop() - { - std::array timestamp; - timestamp.fill(std::chrono::steady_clock::now()); - - std::array, CELL_PAD_MAX_PORT_NUM> button_state; - for (auto& state : button_state) - { - state.fill(true); - } - - input_timer.Start(); - - while (!exit) - { - if (Emu.IsStopped()) - return selection_code::canceled; - - std::this_thread::sleep_for(1ms); - - std::lock_guard lock(pad::g_pad_mutex); - - const auto handler = pad::get_current_handler(); - - const PadInfo& rinfo = handler->GetInfo(); - - if (Emu.IsPaused() || !rinfo.now_connect) - { - continue; - } - - int pad_index = -1; - for (const auto &pad : handler->GetPads()) - { - if (++pad_index >= CELL_PAD_MAX_PORT_NUM) - { - LOG_FATAL(RSX, "The native overlay cannot handle more than 7 pads! Current number of pads: %d", pad_index + 1); - continue; - } - - for (auto &button : pad->m_buttons) - { - u8 button_id = 255; - if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL1) - { - switch (button.m_outKeyCode) - { - case CELL_PAD_CTRL_LEFT: - button_id = pad_button::dpad_left; - break; - case CELL_PAD_CTRL_RIGHT: - button_id = pad_button::dpad_right; - break; - case CELL_PAD_CTRL_DOWN: - button_id = pad_button::dpad_down; - break; - case CELL_PAD_CTRL_UP: - button_id = pad_button::dpad_up; - break; - } - } - else if (button.m_offset == CELL_PAD_BTN_OFFSET_DIGITAL2) - { - switch (button.m_outKeyCode) - { - case CELL_PAD_CTRL_TRIANGLE: - button_id = pad_button::triangle; - break; - case CELL_PAD_CTRL_CIRCLE: - button_id = g_cfg.sys.enter_button_assignment == enter_button_assign::circle ? pad_button::cross : pad_button::circle; - break; - case CELL_PAD_CTRL_SQUARE: - button_id = pad_button::square; - break; - case CELL_PAD_CTRL_CROSS: - button_id = g_cfg.sys.enter_button_assignment == enter_button_assign::circle ? pad_button::circle : pad_button::cross; - break; - } - } - - if (button_id < 255) - { - if (button.m_pressed) - { - if (button_id < 4) // d-pad button - { - if (!button_state[pad_index][button_id] || input_timer.GetMsSince(timestamp[pad_index]) > 400) - { - // d-pad button was not pressed, or was pressed more than 400ms ago - timestamp[pad_index] = std::chrono::steady_clock::now(); - on_button_pressed(static_cast(button_id)); - } - } - else if (!button_state[pad_index][button_id]) - { - // button was not pressed - on_button_pressed(static_cast(button_id)); - } - } - - button_state[pad_index][button_id] = button.m_pressed; - } - - if (button.m_flush) - { - button.m_pressed = false; - button.m_flush = false; - button.m_value = 0; - } - - if (exit) - return 0; - } - } - - refresh(); - } - - // Unreachable - return 0; - } + s32 run_input_loop(); }; class display_manager diff --git a/rpcs3/mm_joystick_handler.cpp b/rpcs3/mm_joystick_handler.cpp index e64b548c42..6a92cfe9d7 100644 --- a/rpcs3/mm_joystick_handler.cpp +++ b/rpcs3/mm_joystick_handler.cpp @@ -316,9 +316,11 @@ void mm_joystick_handler::GetNextButtonPress(const std::string& padId, const std switch (status) { case JOYERR_UNPLUGGED: + { return fail_callback(padId); - + } case JOYERR_NOERROR: + { auto data = GetButtonValues(js_info, js_caps); // Check for each button in our list if its corresponding (maybe remapped) button or axis was pressed. @@ -421,6 +423,9 @@ void mm_joystick_handler::GetNextButtonPress(const std::string& padId, const std break; } + default: + break; + } } void mm_joystick_handler::TranslateButtonPress(u64 keyCode, bool& pressed, u16& val, bool ignore_threshold) diff --git a/rpcs3/pad_thread.cpp b/rpcs3/pad_thread.cpp index 3e42d62211..cd75868722 100644 --- a/rpcs3/pad_thread.cpp +++ b/rpcs3/pad_thread.cpp @@ -57,8 +57,10 @@ void pad_thread::Init() } } + const u32 system_info = m_info.system_info; std::memset(&m_info, 0, sizeof(m_info)); m_info.now_connect = 0; + m_info.system_info |= system_info; m_pads.clear(); handlers.clear(); @@ -147,6 +149,18 @@ void pad_thread::SetEnabled(bool enabled) is_enabled = enabled; } +void pad_thread::SetIntercepted(bool intercepted) +{ + if (intercepted) + { + m_info.system_info |= CELL_PAD_INFO_INTERCEPTED; + } + else + { + m_info.system_info &= ~CELL_PAD_INFO_INTERCEPTED; + } +} + void pad_thread::ThreadFunc() { active = true; diff --git a/rpcs3/pad_thread.h b/rpcs3/pad_thread.h index 6ef1600c82..37efebc081 100644 --- a/rpcs3/pad_thread.h +++ b/rpcs3/pad_thread.h @@ -25,6 +25,7 @@ public: void Init(); void Reset(); void SetEnabled(bool enabled); + void SetIntercepted(bool intercepted); protected: void ThreadFunc(); @@ -36,7 +37,7 @@ protected: void *curthread; void *curwindow; - PadInfo m_info; + PadInfo m_info{ 0, 0 }; std::vector> m_pads; atomic_t active{ false }; @@ -54,4 +55,11 @@ namespace pad { return verify(HERE, g_current.load()); }; + + static inline void SetIntercepted(bool intercepted) + { + std::lock_guard lock(g_pad_mutex); + const auto handler = get_current_handler(); + handler->SetIntercepted(intercepted); + } } diff --git a/rpcs3/rpcs3qt/msg_dialog_frame.cpp b/rpcs3/rpcs3qt/msg_dialog_frame.cpp index 5806c94058..e82426cfa8 100644 --- a/rpcs3/rpcs3qt/msg_dialog_frame.cpp +++ b/rpcs3/rpcs3qt/msg_dialog_frame.cpp @@ -24,7 +24,7 @@ void msg_dialog_frame::Create(const std::string& msg, const std::string& title) m_text = new QLabel(qstr(msg)); m_text->setAlignment(Qt::AlignCenter); - //Layout + // Layout QFormLayout* layout = new QFormLayout(m_dialog); layout->setFormAlignment(Qt::AlignHCenter); layout->addRow(m_text); @@ -140,7 +140,7 @@ void msg_dialog_frame::Create(const std::string& msg, const std::string& title) } }); - //Fix size + // Fix size m_dialog->layout()->setSizeConstraint(QLayout::SetFixedSize); m_dialog->show(); @@ -164,30 +164,30 @@ void msg_dialog_frame::CreateOsk(const std::string& msg, char16_t* osk_text, u32 m_osk_dialog->setModal(true); m_osk_text_return = osk_text; - //Title + // Title m_osk_dialog->setWindowTitle(qstr(msg)); - //Text Input + // Text Input QLineEdit* input = new QLineEdit(m_osk_dialog); input->setFixedWidth(lineEditWidth()); input->setMaxLength(charlimit); input->setText(QString::fromStdU16String(std::u16string(m_osk_text_return))); input->setFocus(); - //Text Input Counter + // Text Input Counter QLabel* inputCount = new QLabel(QString("%1/%2").arg(input->text().length()).arg(charlimit)); - //Ok Button + // Ok Button QPushButton* button_ok = new QPushButton("Ok", m_osk_dialog); - //Button Layout + // Button Layout QHBoxLayout* buttonsLayout = new QHBoxLayout; buttonsLayout->setAlignment(Qt::AlignCenter); buttonsLayout->addStretch(); buttonsLayout->addWidget(button_ok); buttonsLayout->addStretch(); - //Input Layout + // Input Layout QHBoxLayout* inputLayout = new QHBoxLayout; inputLayout->setAlignment(Qt::AlignHCenter); inputLayout->addWidget(input); @@ -199,7 +199,7 @@ void msg_dialog_frame::CreateOsk(const std::string& msg, char16_t* osk_text, u32 layout->addRow(buttonsLayout); m_osk_dialog->setLayout(layout); - //Events + // Events connect(input, &QLineEdit::textChanged, [=](const QString& text) { inputCount->setText(QString("%1/%2").arg(text.length()).arg(charlimit)); @@ -223,7 +223,7 @@ void msg_dialog_frame::CreateOsk(const std::string& msg, char16_t* osk_text, u32 on_close(CELL_MSGDIALOG_BUTTON_OK); }); - //Fix size + // Fix size m_osk_dialog->layout()->setSizeConstraint(QLayout::SetFixedSize); m_osk_dialog->show(); } @@ -385,7 +385,7 @@ void msg_dialog_frame::UpdateProgress(int progress, bool disable) properties.insert(QStringLiteral("progress-visible"), false); else properties.insert(QStringLiteral("progress-visible"), true); - //Progress takes a value from 0.0 to 0.1 + // Progress takes a value from 0.0 to 0.1 properties.insert(QStringLiteral("progress"), (double)progress/(double)m_gauge_max); message << QStringLiteral("application://rpcs3.desktop") << properties; QDBusConnection::sessionBus().send(message); diff --git a/rpcs3/rpcs3qt/msg_dialog_frame.h b/rpcs3/rpcs3qt/msg_dialog_frame.h index f4c171852b..ded9780655 100644 --- a/rpcs3/rpcs3qt/msg_dialog_frame.h +++ b/rpcs3/rpcs3qt/msg_dialog_frame.h @@ -51,7 +51,7 @@ private: QProgressBar* m_gauge1 = nullptr; QProgressBar* m_gauge2 = nullptr; - QWindow* m_taskbarTarget; // Window which will be targeted by custom taskbars. + QWindow* m_taskbarTarget; // Window which will be targeted by custom taskbars. custom_dialog* m_osk_dialog = nullptr; char16_t* m_osk_text_return; diff --git a/rpcs3/rpcs3qt/save_data_dialog.cpp b/rpcs3/rpcs3qt/save_data_dialog.cpp index cb1cd7014f..6f422b925e 100644 --- a/rpcs3/rpcs3qt/save_data_dialog.cpp +++ b/rpcs3/rpcs3qt/save_data_dialog.cpp @@ -6,7 +6,7 @@ s32 save_data_dialog::ShowSaveDataList(std::vector& save_entries, s32 focused, u32 op, vm::ptr listSet) { - //TODO: Install native shell as an Emu callback + // TODO: Install native shell as an Emu callback if (auto manager = fxm::get()) { auto result = manager->create()->show(save_entries, op, listSet); @@ -14,10 +14,12 @@ s32 save_data_dialog::ShowSaveDataList(std::vector& save_entries, return result; } - //Fall back to front-end GUI + // Fall back to front-end GUI atomic_t dlg_result(false); atomic_t selection; + pad::SetIntercepted(true); + Emu.CallAfter([&]() { save_data_list_dialog sdid(save_entries, focused, op, listSet); @@ -31,5 +33,7 @@ s32 save_data_dialog::ShowSaveDataList(std::vector& save_entries, thread_ctrl::wait_for(1000); } + pad::SetIntercepted(false); + return selection.load(); } diff --git a/rpcs3/xinput_pad_handler.cpp b/rpcs3/xinput_pad_handler.cpp index 14f40942ce..e24424a5f6 100644 --- a/rpcs3/xinput_pad_handler.cpp +++ b/rpcs3/xinput_pad_handler.cpp @@ -328,6 +328,7 @@ void xinput_pad_handler::ThreadProc() switch (result) { case ERROR_DEVICE_NOT_CONNECTED: + { if (last_connection_status[i] == true) { LOG_ERROR(HLE, "XInput device %d disconnected", padnum); @@ -337,8 +338,9 @@ void xinput_pad_handler::ThreadProc() connected--; } continue; - + } case ERROR_SUCCESS: + { if (last_connection_status[i] == false) { LOG_SUCCESS(HLE, "XInput device %d reconnected", padnum); @@ -437,7 +439,9 @@ void xinput_pad_handler::ThreadProc() m_dev->last_vibration = clock(); } } - + break; + } + default: break; } }