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
target_sources(rpcs3_emu PRIVATE
Io/interception.cpp
Io/KeyboardHandler.cpp
Io/pad_config.cpp
Io/pad_config_types.cpp

View File

@ -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<u32> max_connect;

View File

@ -129,9 +129,13 @@ error_code cellMouseGetInfo(vm::ptr<CellMouseInfo> info)
info->max_connect = current_info.max_connect;
info->now_connect = current_info.now_connect;
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++) info->status[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;
}

View File

@ -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<char> msgString,
g_fxo->get<msg_info>()->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<msg_dlg_thread>()->wait_until = 0;
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;
}

View File

@ -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<CellOskDialogParam> 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<CellOskDialogParam> 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<OskDialogBase>(osk)]()
@ -240,7 +240,7 @@ error_code cellOskDialogLoadAsync(u32 container, vm::ptr<CellOskDialogParam> dia
}
};
pad::SetIntercepted(true);
input::SetIntercepted(true);
Emu.CallAfter([=, &result]()
{

View File

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

View File

@ -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<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
{
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<u16, u32> 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);

View File

@ -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<Mouse>& GetMice() { return m_mice; }
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 "../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)

View File

@ -3,6 +3,7 @@
#include <QApplication>
#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;
}

View File

@ -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)

View File

@ -97,6 +97,7 @@
</ClCompile>
<ClCompile Include="Emu\Io\GHLtar.cpp" />
<ClCompile Include="Emu\Audio\AudioBackend.cpp" />
<ClCompile Include="Emu\Io\interception.cpp" />
<ClCompile Include="Emu\Io\KeyboardHandler.cpp" />
<ClCompile Include="Emu\Io\pad_config.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\cellStorage.h" />
<ClInclude Include="Emu\Io\GHLtar.h" />
<ClInclude Include="Emu\Io\interception.h" />
<ClInclude Include="Emu\Io\pad_types.h" />
<ClInclude Include="Emu\Io\Keyboard.h" />
<ClInclude Include="Emu\Io\pad_config.h" />

View File

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

View File

@ -3,10 +3,9 @@
#include <Emu/System.h>
#include <Emu/IdManager.h>
#include "Emu/Io/interception.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)
{
// 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<s32> selection;
pad::SetIntercepted(true);
input::SetIntercepted(true);
Emu.CallAfter([&]()
{
@ -41,7 +40,7 @@ s32 save_data_dialog::ShowSaveDataList(std::vector<SaveDataEntry>& save_entries,
thread_ctrl::wait_for(1000);
}
pad::SetIntercepted(false);
input::SetIntercepted(false);
return selection.load();
}