implement interception for cellKb and cellMouse

this needs to be tested
This commit is contained in:
Megamouse 2020-10-04 22:46:28 +02:00 committed by Ivan
parent c65b7d0aea
commit 4984e87776
17 changed files with 130 additions and 31 deletions

View file

@ -352,6 +352,7 @@ target_link_libraries(rpcs3_emu
# Io # Io
target_sources(rpcs3_emu PRIVATE target_sources(rpcs3_emu PRIVATE
Io/interception.cpp
Io/KeyboardHandler.cpp Io/KeyboardHandler.cpp
Io/pad_config.cpp Io/pad_config.cpp
Io/pad_config_types.cpp Io/pad_config_types.cpp

View file

@ -35,11 +35,6 @@ enum
CELL_KB_ARRANGEMENT_106_KANA = CELL_KB_MAPPING_106_KANA, CELL_KB_ARRANGEMENT_106_KANA = CELL_KB_MAPPING_106_KANA,
}; };
enum
{
CELL_KB_INFO_INTERCEPTED = 1
};
struct CellKbInfo struct CellKbInfo
{ {
be_t<u32> max_connect; be_t<u32> max_connect;

View file

@ -129,9 +129,13 @@ error_code cellMouseGetInfo(vm::ptr<CellMouseInfo> info)
info->max_connect = current_info.max_connect; info->max_connect = current_info.max_connect;
info->now_connect = current_info.now_connect; info->now_connect = current_info.now_connect;
info->info = current_info.info; info->info = current_info.info;
for (u32 i=0; i<CELL_MAX_MICE; i++) info->vendor_id[i] = current_info.vendor_id[i];
for (u32 i=0; i<CELL_MAX_MICE; i++) info->product_id[i] = current_info.product_id[i]; for (u32 i = 0; i < CELL_MAX_MICE; i++)
for (u32 i=0; i<CELL_MAX_MICE; i++) info->status[i] = current_info.status[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; return CELL_OK;
} }

View file

@ -2,10 +2,9 @@
#include "Emu/Cell/PPUModule.h" #include "Emu/Cell/PPUModule.h"
#include "Emu/Cell/PPUThread.h" #include "Emu/Cell/PPUThread.h"
#include "Emu/Cell/lv2/sys_sync.h" #include "Emu/Cell/lv2/sys_sync.h"
#include "Emu/Io/interception.h"
#include "Emu/RSX/Overlays/overlay_message_dialog.h" #include "Emu/RSX/Overlays/overlay_message_dialog.h"
#include "Input/pad_thread.h"
#include "cellSysutil.h" #include "cellSysutil.h"
#include "cellMsgDialog.h" #include "cellMsgDialog.h"
@ -201,10 +200,10 @@ error_code open_msg_dialog(bool is_blocking, u32 type, vm::cptr<char> msgString,
g_fxo->get<msg_info>()->remove(); g_fxo->get<msg_info>()->remove();
} }
pad::SetIntercepted(false); input::SetIntercepted(false);
}; };
pad::SetIntercepted(true); input::SetIntercepted(true);
auto& ppu = *get_current_cpu_thread(); auto& ppu = *get_current_cpu_thread();
lv2_obj::sleep(ppu); lv2_obj::sleep(ppu);
@ -482,7 +481,7 @@ error_code cellMsgDialogAbort()
g_fxo->get<msg_dlg_thread>()->wait_until = 0; g_fxo->get<msg_dlg_thread>()->wait_until = 0;
g_fxo->get<msg_info>()->remove(); // this shouldn't call on_close g_fxo->get<msg_info>()->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; return CELL_OK;
} }

View file

@ -2,8 +2,8 @@
#include "Emu/System.h" #include "Emu/System.h"
#include "Emu/system_config.h" #include "Emu/system_config.h"
#include "Emu/Cell/PPUModule.h" #include "Emu/Cell/PPUModule.h"
#include "Emu/Io/interception.h"
#include "Emu/RSX/Overlays/overlay_osk.h" #include "Emu/RSX/Overlays/overlay_osk.h"
#include "Input/pad_thread.h"
#include "cellSysutil.h" #include "cellSysutil.h"
#include "cellOskDialog.h" #include "cellOskDialog.h"
@ -152,7 +152,7 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dia
return false; return false;
})) }))
{ {
pad::SetIntercepted(false); input::SetIntercepted(false);
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_FINISHED, 0); sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_FINISHED, 0);
return; return;
} }
@ -227,7 +227,7 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dia
sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_FINISHED, 0); sysutil_send_system_cmd(CELL_SYSUTIL_OSKDIALOG_FINISHED, 0);
} }
pad::SetIntercepted(false); input::SetIntercepted(false);
}; };
osk->on_osk_input_entered = [wptr = std::weak_ptr<OskDialogBase>(osk)]() osk->on_osk_input_entered = [wptr = std::weak_ptr<OskDialogBase>(osk)]()
@ -240,7 +240,7 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dia
} }
}; };
pad::SetIntercepted(true); input::SetIntercepted(true);
Emu.CallAfter([=, &result]() Emu.CallAfter([=, &result]()
{ {

View file

@ -2,6 +2,11 @@
#include "Utilities/types.h" #include "Utilities/types.h"
enum
{
CELL_KB_INFO_INTERCEPTED = 1
};
enum enum
{ {
CELL_KB_MAX_KEYCODES = 62, CELL_KB_MAX_KEYCODES = 62,

View file

@ -165,3 +165,24 @@ bool KeyboardHandlerBase::IsMetaKey(u32 code)
|| code == Key_Super_L || code == Key_Super_L
|| code == Key_Super_R; || code == Key_Super_R;
} }
void KeyboardHandlerBase::SetIntercepted(bool intercepted)
{
std::lock_guard<std::mutex> 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;
}
}
}
}

View file

@ -31,9 +31,9 @@ struct KbInfo
struct KbData struct KbData
{ {
u32 led; u32 led; // Active led lights
u32 mkey; u32 mkey; // Active key modifiers
s32 len; s32 len; // Number of key codes (0 means no data available)
std::pair<u16, u32> keycode[CELL_KB_MAX_KEYCODES]; std::pair<u16, u32> keycode[CELL_KB_MAX_KEYCODES];
KbData() KbData()
@ -99,6 +99,7 @@ public:
virtual ~KeyboardHandlerBase() = default; virtual ~KeyboardHandlerBase() = default;
void Key(u32 code, bool pressed); void Key(u32 code, bool pressed);
void SetIntercepted(bool intercepted);
bool IsMetaKey(u32 code); bool IsMetaKey(u32 code);

View file

@ -41,6 +41,11 @@ enum MouseButtonCodes
CELL_MOUSE_BUTTON_8 = 0x00000080, CELL_MOUSE_BUTTON_8 = 0x00000080,
}; };
enum
{
CELL_MOUSE_INFO_INTERCEPTED = 1
};
static const u32 MAX_MICE = 127; static const u32 MAX_MICE = 127;
static const u32 MOUSE_MAX_DATA_LIST_NUM = 8; static const u32 MOUSE_MAX_DATA_LIST_NUM = 8;
static const u32 MOUSE_MAX_CODES = 64; 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; } MouseInfo& GetInfo() { return m_info; }
std::vector<Mouse>& GetMice() { return m_mice; } std::vector<Mouse>& GetMice() { return m_mice; }
MouseDataList& GetDataList(const u32 mouse) { return m_mice[mouse].m_datalist; } MouseDataList& GetDataList(const u32 mouse) { return m_mice[mouse].m_datalist; }

View file

@ -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<bool> g_intercepted{false};
void SetIntercepted(bool intercepted)
{
g_intercepted = intercepted;
pad::SetIntercepted(intercepted);
if (const auto handler = g_fxo->get<KeyboardHandlerBase>())
{
handler->SetIntercepted(intercepted);
}
if (const auto handler = g_fxo->get<MouseHandlerBase>())
{
handler->SetIntercepted(intercepted);
}
}
}

View file

@ -0,0 +1,10 @@
#pragma once
#include <atomic>
namespace input
{
extern std::atomic<bool> g_intercepted;
void SetIntercepted(bool intercepted);
}

View file

@ -3,6 +3,7 @@
#include "overlay_message_dialog.h" #include "overlay_message_dialog.h"
#include "../GSRender.h" #include "../GSRender.h"
#include "Input/pad_thread.h" #include "Input/pad_thread.h"
#include "Emu/Io/interception.h"
LOG_CHANNEL(overlays); LOG_CHANNEL(overlays);
@ -58,7 +59,7 @@ namespace rsx
input_timer.Start(); input_timer.Start();
pad::SetIntercepted(true); input::SetIntercepted(true);
while (!exit) while (!exit)
{ {
@ -205,7 +206,7 @@ namespace rsx
if (stop_pad_interception) if (stop_pad_interception)
{ {
pad::SetIntercepted(false); input::SetIntercepted(false);
} }
if (on_close && use_callback) if (on_close && use_callback)

View file

@ -3,6 +3,7 @@
#include <QApplication> #include <QApplication>
#include "Emu/system_config.h" #include "Emu/system_config.h"
#include "Emu/Io/interception.h"
#ifdef _WIN32 #ifdef _WIN32
#include "windows.h" #include "windows.h"
@ -25,7 +26,7 @@ void basic_keyboard_handler::Init(const u32 max_connect)
memset(&m_info, 0, sizeof(KbInfo)); memset(&m_info, 0, sizeof(KbInfo));
m_info.max_connect = max_connect; m_info.max_connect = max_connect;
m_info.now_connect = std::min(::size32(m_keyboards), 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.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) m_info.status[0] = CELL_KB_STATUS_CONNECTED; // (TODO: Support for more keyboards)
} }
@ -52,7 +53,7 @@ void basic_keyboard_handler::SetTargetWindow(QWindow* target)
bool basic_keyboard_handler::eventFilter(QObject* target, QEvent* ev) bool basic_keyboard_handler::eventFilter(QObject* target, QEvent* ev)
{ {
if (!ev) if (!ev || input::g_intercepted)
{ {
return false; return false;
} }

View file

@ -3,6 +3,7 @@
#include "basic_mouse_handler.h" #include "basic_mouse_handler.h"
#include "rpcs3qt/gs_frame.h" #include "rpcs3qt/gs_frame.h"
#include "Emu/Io/interception.h"
LOG_CHANNEL(input_log, "Input"); LOG_CHANNEL(input_log, "Input");
@ -12,7 +13,7 @@ void basic_mouse_handler::Init(const u32 max_connect)
memset(&m_info, 0, sizeof(MouseInfo)); memset(&m_info, 0, sizeof(MouseInfo));
m_info.max_connect = max_connect; m_info.max_connect = max_connect;
m_info.now_connect = std::min(::size32(m_mice), 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++) for (u32 i = 1; i < max_connect; i++)
{ {
m_info.status[i] = CELL_MOUSE_STATUS_DISCONNECTED; m_info.status[i] = CELL_MOUSE_STATUS_DISCONNECTED;
@ -46,6 +47,11 @@ void basic_mouse_handler::SetTargetWindow(QWindow* target)
bool basic_mouse_handler::eventFilter(QObject* target, QEvent* ev) 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 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) // !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) if (!m_target || !m_target->isVisible() || target == m_target)

View file

@ -97,6 +97,7 @@
</ClCompile> </ClCompile>
<ClCompile Include="Emu\Io\GHLtar.cpp" /> <ClCompile Include="Emu\Io\GHLtar.cpp" />
<ClCompile Include="Emu\Audio\AudioBackend.cpp" /> <ClCompile Include="Emu\Audio\AudioBackend.cpp" />
<ClCompile Include="Emu\Io\interception.cpp" />
<ClCompile Include="Emu\Io\KeyboardHandler.cpp" /> <ClCompile Include="Emu\Io\KeyboardHandler.cpp" />
<ClCompile Include="Emu\Io\pad_config.cpp" /> <ClCompile Include="Emu\Io\pad_config.cpp" />
<ClCompile Include="Emu\Io\pad_config_types.cpp" /> <ClCompile Include="Emu\Io\pad_config_types.cpp" />
@ -486,6 +487,7 @@
<ClInclude Include="Emu\Cell\Modules\cellSsl.h" /> <ClInclude Include="Emu\Cell\Modules\cellSsl.h" />
<ClInclude Include="Emu\Cell\Modules\cellStorage.h" /> <ClInclude Include="Emu\Cell\Modules\cellStorage.h" />
<ClInclude Include="Emu\Io\GHLtar.h" /> <ClInclude Include="Emu\Io\GHLtar.h" />
<ClInclude Include="Emu\Io\interception.h" />
<ClInclude Include="Emu\Io\pad_types.h" /> <ClInclude Include="Emu\Io\pad_types.h" />
<ClInclude Include="Emu\Io\Keyboard.h" /> <ClInclude Include="Emu\Io\Keyboard.h" />
<ClInclude Include="Emu\Io\pad_config.h" /> <ClInclude Include="Emu\Io\pad_config.h" />

View file

@ -974,6 +974,9 @@
<ClCompile Include="Emu\perf_meter.cpp"> <ClCompile Include="Emu\perf_meter.cpp">
<Filter>Emu</Filter> <Filter>Emu</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="Emu\Io\interception.cpp">
<Filter>Emu\Io</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClInclude Include="Crypto\aes.h"> <ClInclude Include="Crypto\aes.h">
@ -1873,6 +1876,9 @@
<ClInclude Include="Emu\perf_meter.hpp"> <ClInclude Include="Emu\perf_meter.hpp">
<Filter>Emu</Filter> <Filter>Emu</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="Emu\Io\interception.h">
<Filter>Emu\Io</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<None Include="Emu\RSX\Common\Interpreter\FragmentInterpreter.glsl"> <None Include="Emu\RSX\Common\Interpreter\FragmentInterpreter.glsl">

View file

@ -3,10 +3,9 @@
#include <Emu/System.h> #include <Emu/System.h>
#include <Emu/IdManager.h> #include <Emu/IdManager.h>
#include "Emu/Io/interception.h"
#include <Emu/RSX/Overlays/overlay_save_dialog.h> #include <Emu/RSX/Overlays/overlay_save_dialog.h>
#include "Input/pad_thread.h"
s32 save_data_dialog::ShowSaveDataList(std::vector<SaveDataEntry>& save_entries, s32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet) s32 save_data_dialog::ShowSaveDataList(std::vector<SaveDataEntry>& save_entries, s32 focused, u32 op, vm::ptr<CellSaveDataListSet> listSet)
{ {
// TODO: Install native shell as an Emu callback // TODO: Install native shell as an Emu callback
@ -26,7 +25,7 @@ s32 save_data_dialog::ShowSaveDataList(std::vector<SaveDataEntry>& save_entries,
atomic_t<bool> dlg_result(false); atomic_t<bool> dlg_result(false);
atomic_t<s32> selection; atomic_t<s32> selection;
pad::SetIntercepted(true); input::SetIntercepted(true);
Emu.CallAfter([&]() Emu.CallAfter([&]()
{ {
@ -41,7 +40,7 @@ s32 save_data_dialog::ShowSaveDataList(std::vector<SaveDataEntry>& save_entries,
thread_ctrl::wait_for(1000); thread_ctrl::wait_for(1000);
} }
pad::SetIntercepted(false); input::SetIntercepted(false);
return selection.load(); return selection.load();
} }