diff --git a/rpcs3/Emu/CMakeLists.txt b/rpcs3/Emu/CMakeLists.txt index d6d089b949..f02e072a61 100644 --- a/rpcs3/Emu/CMakeLists.txt +++ b/rpcs3/Emu/CMakeLists.txt @@ -352,6 +352,7 @@ target_link_libraries(rpcs3_emu # Io target_sources(rpcs3_emu PRIVATE + Io/interception.cpp Io/KeyboardHandler.cpp Io/pad_config.cpp Io/pad_config_types.cpp diff --git a/rpcs3/Emu/Cell/Modules/cellKb.h b/rpcs3/Emu/Cell/Modules/cellKb.h index 139a7dbb3a..8bc69eb27b 100644 --- a/rpcs3/Emu/Cell/Modules/cellKb.h +++ b/rpcs3/Emu/Cell/Modules/cellKb.h @@ -35,11 +35,6 @@ enum CELL_KB_ARRANGEMENT_106_KANA = CELL_KB_MAPPING_106_KANA, }; -enum -{ - CELL_KB_INFO_INTERCEPTED = 1 -}; - struct CellKbInfo { be_t max_connect; diff --git a/rpcs3/Emu/Cell/Modules/cellMouse.cpp b/rpcs3/Emu/Cell/Modules/cellMouse.cpp index a74d1590b6..17cbedc8b7 100644 --- a/rpcs3/Emu/Cell/Modules/cellMouse.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMouse.cpp @@ -129,9 +129,13 @@ error_code cellMouseGetInfo(vm::ptr info) info->max_connect = current_info.max_connect; info->now_connect = current_info.now_connect; info->info = current_info.info; - for (u32 i=0; ivendor_id[i] = current_info.vendor_id[i]; - for (u32 i=0; iproduct_id[i] = current_info.product_id[i]; - for (u32 i=0; istatus[i] = current_info.status[i]; + + for (u32 i = 0; i < CELL_MAX_MICE; i++) + { + info->vendor_id[i] = current_info.vendor_id[i]; + info->product_id[i] = current_info.product_id[i]; + info->status[i] = current_info.status[i]; + } return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp b/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp index 740977a9fa..26c7d60948 100644 --- a/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp +++ b/rpcs3/Emu/Cell/Modules/cellMsgDialog.cpp @@ -2,10 +2,9 @@ #include "Emu/Cell/PPUModule.h" #include "Emu/Cell/PPUThread.h" #include "Emu/Cell/lv2/sys_sync.h" +#include "Emu/Io/interception.h" #include "Emu/RSX/Overlays/overlay_message_dialog.h" -#include "Input/pad_thread.h" - #include "cellSysutil.h" #include "cellMsgDialog.h" @@ -201,10 +200,10 @@ error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr msgString, g_fxo->get()->remove(); } - pad::SetIntercepted(false); + input::SetIntercepted(false); }; - pad::SetIntercepted(true); + input::SetIntercepted(true); auto& ppu = *get_current_cpu_thread(); lv2_obj::sleep(ppu); @@ -482,7 +481,7 @@ error_code cellMsgDialogAbort() g_fxo->get()->wait_until = 0; g_fxo->get()->remove(); // this shouldn't call on_close - pad::SetIntercepted(false); // so we need to reenable the pads here + input::SetIntercepted(false); // so we need to reenable the pads here return CELL_OK; } diff --git a/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp b/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp index 3415d8c378..5603b069f4 100644 --- a/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp +++ b/rpcs3/Emu/Cell/Modules/cellOskDialog.cpp @@ -2,8 +2,8 @@ #include "Emu/System.h" #include "Emu/system_config.h" #include "Emu/Cell/PPUModule.h" +#include "Emu/Io/interception.h" #include "Emu/RSX/Overlays/overlay_osk.h" -#include "Input/pad_thread.h" #include "cellSysutil.h" #include "cellOskDialog.h" @@ -152,7 +152,7 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr dia return false; })) { - pad::SetIntercepted(false); + input::SetIntercepted(false); sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_FINISHED, 0); return; } @@ -227,7 +227,7 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr dia sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_FINISHED, 0); } - pad::SetIntercepted(false); + input::SetIntercepted(false); }; osk->on_osk_input_entered = [wptr = std::weak_ptr(osk)]() @@ -240,7 +240,7 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr dia } }; - pad::SetIntercepted(true); + input::SetIntercepted(true); Emu.CallAfter([=, &result]() { diff --git a/rpcs3/Emu/Io/Keyboard.h b/rpcs3/Emu/Io/Keyboard.h index c7682c3c88..25e5776001 100644 --- a/rpcs3/Emu/Io/Keyboard.h +++ b/rpcs3/Emu/Io/Keyboard.h @@ -2,6 +2,11 @@ #include "Utilities/types.h" +enum +{ + CELL_KB_INFO_INTERCEPTED = 1 +}; + enum { CELL_KB_MAX_KEYCODES = 62, diff --git a/rpcs3/Emu/Io/KeyboardHandler.cpp b/rpcs3/Emu/Io/KeyboardHandler.cpp index a54c32cace..7d02c9ff6b 100644 --- a/rpcs3/Emu/Io/KeyboardHandler.cpp +++ b/rpcs3/Emu/Io/KeyboardHandler.cpp @@ -165,3 +165,24 @@ bool KeyboardHandlerBase::IsMetaKey(u32 code) || code == Key_Super_L || code == Key_Super_R; } + +void KeyboardHandlerBase::SetIntercepted(bool intercepted) +{ + std::lock_guard lock(m_mutex); + + m_info.info = intercepted ? CELL_KB_INFO_INTERCEPTED : 0; + + if (intercepted) + { + for (Keyboard& keyboard : m_keyboards) + { + keyboard.m_data.mkey = 0; + keyboard.m_data.len = 0; + + for (auto& keycode : keyboard.m_data.keycode) + { + keycode.first = CELL_KEYC_NO_EVENT; + } + } + } +} diff --git a/rpcs3/Emu/Io/KeyboardHandler.h b/rpcs3/Emu/Io/KeyboardHandler.h index 60a49e6b53..859329c79e 100644 --- a/rpcs3/Emu/Io/KeyboardHandler.h +++ b/rpcs3/Emu/Io/KeyboardHandler.h @@ -31,9 +31,9 @@ struct KbInfo struct KbData { - u32 led; - u32 mkey; - s32 len; + u32 led; // Active led lights + u32 mkey; // Active key modifiers + s32 len; // Number of key codes (0 means no data available) std::pair keycode[CELL_KB_MAX_KEYCODES]; KbData() @@ -99,6 +99,7 @@ public: virtual ~KeyboardHandlerBase() = default; void Key(u32 code, bool pressed); + void SetIntercepted(bool intercepted); bool IsMetaKey(u32 code); diff --git a/rpcs3/Emu/Io/MouseHandler.h b/rpcs3/Emu/Io/MouseHandler.h index ecd18166e5..04c66ed20a 100644 --- a/rpcs3/Emu/Io/MouseHandler.h +++ b/rpcs3/Emu/Io/MouseHandler.h @@ -41,6 +41,11 @@ enum MouseButtonCodes CELL_MOUSE_BUTTON_8 = 0x00000080, }; +enum +{ + CELL_MOUSE_INFO_INTERCEPTED = 1 +}; + static const u32 MAX_MICE = 127; static const u32 MOUSE_MAX_DATA_LIST_NUM = 8; static const u32 MOUSE_MAX_CODES = 64; @@ -251,6 +256,21 @@ public: } } + void SetIntercepted(bool intercepted) + { + std::lock_guard lock(mutex); + + m_info.info = intercepted ? CELL_MOUSE_INFO_INTERCEPTED : 0; + + if (intercepted) + { + for (Mouse& mouse : m_mice) + { + mouse = {}; + } + } + } + MouseInfo& GetInfo() { return m_info; } std::vector& GetMice() { return m_mice; } MouseDataList& GetDataList(const u32 mouse) { return m_mice[mouse].m_datalist; } diff --git a/rpcs3/Emu/Io/interception.cpp b/rpcs3/Emu/Io/interception.cpp new file mode 100644 index 0000000000..fc7cdf9729 --- /dev/null +++ b/rpcs3/Emu/Io/interception.cpp @@ -0,0 +1,28 @@ +#include "stdafx.h" +#include "interception.h" +#include "KeyboardHandler.h" +#include "MouseHandler.h" +#include "Input/pad_thread.h" +#include "Emu/IdManager.h" + +namespace input +{ + std::atomic g_intercepted{false}; + + void SetIntercepted(bool intercepted) + { + g_intercepted = intercepted; + + pad::SetIntercepted(intercepted); + + if (const auto handler = g_fxo->get()) + { + handler->SetIntercepted(intercepted); + } + + if (const auto handler = g_fxo->get()) + { + handler->SetIntercepted(intercepted); + } + } +} diff --git a/rpcs3/Emu/Io/interception.h b/rpcs3/Emu/Io/interception.h new file mode 100644 index 0000000000..48d3fa7b7d --- /dev/null +++ b/rpcs3/Emu/Io/interception.h @@ -0,0 +1,10 @@ +#pragma once + +#include + +namespace input +{ + extern std::atomic g_intercepted; + + void SetIntercepted(bool intercepted); +} diff --git a/rpcs3/Emu/RSX/Overlays/overlays.cpp b/rpcs3/Emu/RSX/Overlays/overlays.cpp index 96b7978973..50ec0e9691 100644 --- a/rpcs3/Emu/RSX/Overlays/overlays.cpp +++ b/rpcs3/Emu/RSX/Overlays/overlays.cpp @@ -3,6 +3,7 @@ #include "overlay_message_dialog.h" #include "../GSRender.h" #include "Input/pad_thread.h" +#include "Emu/Io/interception.h" LOG_CHANNEL(overlays); @@ -58,7 +59,7 @@ namespace rsx input_timer.Start(); - pad::SetIntercepted(true); + input::SetIntercepted(true); while (!exit) { @@ -205,7 +206,7 @@ namespace rsx if (stop_pad_interception) { - pad::SetIntercepted(false); + input::SetIntercepted(false); } if (on_close && use_callback) diff --git a/rpcs3/Input/basic_keyboard_handler.cpp b/rpcs3/Input/basic_keyboard_handler.cpp index e9a7e124ed..c4ddd0517a 100644 --- a/rpcs3/Input/basic_keyboard_handler.cpp +++ b/rpcs3/Input/basic_keyboard_handler.cpp @@ -3,6 +3,7 @@ #include #include "Emu/system_config.h" +#include "Emu/Io/interception.h" #ifdef _WIN32 #include "windows.h" @@ -25,8 +26,8 @@ void basic_keyboard_handler::Init(const u32 max_connect) memset(&m_info, 0, sizeof(KbInfo)); m_info.max_connect = max_connect; m_info.now_connect = std::min(::size32(m_keyboards), max_connect); - m_info.info = 0; // Ownership of keyboard data: 0=Application, 1=System - m_info.status[0] = CELL_KB_STATUS_CONNECTED; // (TODO: Support for more keyboards) + m_info.info = input::g_intercepted ? CELL_KB_INFO_INTERCEPTED : 0; // Ownership of keyboard data: 0=Application, 1=System + m_info.status[0] = CELL_KB_STATUS_CONNECTED; // (TODO: Support for more keyboards) } basic_keyboard_handler::basic_keyboard_handler() : QObject() @@ -52,7 +53,7 @@ void basic_keyboard_handler::SetTargetWindow(QWindow* target) bool basic_keyboard_handler::eventFilter(QObject* target, QEvent* ev) { - if (!ev) + if (!ev || input::g_intercepted) { return false; } diff --git a/rpcs3/Input/basic_mouse_handler.cpp b/rpcs3/Input/basic_mouse_handler.cpp index 7f029a06c4..9de59cf7a1 100644 --- a/rpcs3/Input/basic_mouse_handler.cpp +++ b/rpcs3/Input/basic_mouse_handler.cpp @@ -3,6 +3,7 @@ #include "basic_mouse_handler.h" #include "rpcs3qt/gs_frame.h" +#include "Emu/Io/interception.h" LOG_CHANNEL(input_log, "Input"); @@ -12,14 +13,14 @@ void basic_mouse_handler::Init(const u32 max_connect) memset(&m_info, 0, sizeof(MouseInfo)); m_info.max_connect = max_connect; m_info.now_connect = std::min(::size32(m_mice), max_connect); - m_info.info = 0; // Ownership of mouse data: 0=Application, 1=System + m_info.info = input::g_intercepted ? CELL_MOUSE_INFO_INTERCEPTED : 0; // Ownership of mouse data: 0=Application, 1=System for (u32 i = 1; i < max_connect; i++) { m_info.status[i] = CELL_MOUSE_STATUS_DISCONNECTED; m_info.mode[i] = CELL_MOUSE_INFO_TABLET_MOUSE_MODE; m_info.tablet_is_supported[i] = CELL_MOUSE_INFO_TABLET_NOT_SUPPORTED; } - m_info.status[0] = CELL_MOUSE_STATUS_CONNECTED; // (TODO: Support for more mice) + m_info.status[0] = CELL_MOUSE_STATUS_CONNECTED; // (TODO: Support for more mice) m_info.vendor_id[0] = 0x1234; m_info.product_id[0] = 0x1234; } @@ -46,6 +47,11 @@ void basic_mouse_handler::SetTargetWindow(QWindow* target) bool basic_mouse_handler::eventFilter(QObject* target, QEvent* ev) { + if (!ev || input::g_intercepted) + { + return false; + } + // !m_target is for future proofing when gsrender isn't automatically initialized on load to ensure events still occur // !m_target->isVisible() is a hack since currently a guiless application will STILL inititialize a gsrender (providing a valid target) if (!m_target || !m_target->isVisible() || target == m_target) diff --git a/rpcs3/emucore.vcxproj b/rpcs3/emucore.vcxproj index ba5808de54..f7f97456e2 100644 --- a/rpcs3/emucore.vcxproj +++ b/rpcs3/emucore.vcxproj @@ -97,6 +97,7 @@ + @@ -486,6 +487,7 @@ + diff --git a/rpcs3/emucore.vcxproj.filters b/rpcs3/emucore.vcxproj.filters index bc413b4114..82d33c9822 100644 --- a/rpcs3/emucore.vcxproj.filters +++ b/rpcs3/emucore.vcxproj.filters @@ -974,6 +974,9 @@ Emu + + Emu\Io + @@ -1873,6 +1876,9 @@ Emu + + Emu\Io + diff --git a/rpcs3/rpcs3qt/save_data_dialog.cpp b/rpcs3/rpcs3qt/save_data_dialog.cpp index 6beb6c375c..7bae2aaa74 100644 --- a/rpcs3/rpcs3qt/save_data_dialog.cpp +++ b/rpcs3/rpcs3qt/save_data_dialog.cpp @@ -3,10 +3,9 @@ #include #include +#include "Emu/Io/interception.h" #include -#include "Input/pad_thread.h" - s32 save_data_dialog::ShowSaveDataList(std::vector& save_entries, s32 focused, u32 op, vm::ptr listSet) { // TODO: Install native shell as an Emu callback @@ -26,7 +25,7 @@ s32 save_data_dialog::ShowSaveDataList(std::vector& save_entries, atomic_t dlg_result(false); atomic_t selection; - pad::SetIntercepted(true); + input::SetIntercepted(true); Emu.CallAfter([&]() { @@ -41,7 +40,7 @@ s32 save_data_dialog::ShowSaveDataList(std::vector& save_entries, thread_ctrl::wait_for(1000); } - pad::SetIntercepted(false); + input::SetIntercepted(false); return selection.load(); }