mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-25 12:12:50 +01:00
input: use keyboard consumers to seperate cell and overlay logic
This commit is contained in:
parent
6fc7fa3b13
commit
fcba193a3c
3
.gitignore
vendored
3
.gitignore
vendored
@ -130,6 +130,9 @@ yaml-cpp.pc
|
|||||||
# miniupnp
|
# miniupnp
|
||||||
/3rdparty/miniupnp/x64/*
|
/3rdparty/miniupnp/x64/*
|
||||||
|
|
||||||
|
# opencv
|
||||||
|
/3rdparty/opencv/*
|
||||||
|
|
||||||
# llvm
|
# llvm
|
||||||
/3rdparty/llvm/llvm_build
|
/3rdparty/llvm/llvm_build
|
||||||
|
|
||||||
|
@ -42,13 +42,16 @@ KeyboardHandlerBase::KeyboardHandlerBase(utils::serial* ar)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
(*ar)(m_info.max_connect);
|
u32 max_connect = 0;
|
||||||
|
|
||||||
if (m_info.max_connect)
|
(*ar)(max_connect);
|
||||||
|
|
||||||
|
if (max_connect)
|
||||||
{
|
{
|
||||||
Emu.PostponeInitCode([this]()
|
Emu.PostponeInitCode([this, max_connect]()
|
||||||
{
|
{
|
||||||
Init(m_info.max_connect);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
AddConsumer(keyboard_consumer::identifier::cellKb, max_connect);
|
||||||
auto lk = init.init();
|
auto lk = init.init();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -56,9 +59,20 @@ KeyboardHandlerBase::KeyboardHandlerBase(utils::serial* ar)
|
|||||||
|
|
||||||
void KeyboardHandlerBase::save(utils::serial& ar)
|
void KeyboardHandlerBase::save(utils::serial& ar)
|
||||||
{
|
{
|
||||||
|
u32 max_connect = 0;
|
||||||
const auto inited = init.access();
|
const auto inited = init.access();
|
||||||
|
|
||||||
ar(inited ? m_info.max_connect : 0);
|
if (inited)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
|
if (auto it = m_consumers.find(keyboard_consumer::identifier::cellKb); it != m_consumers.end())
|
||||||
|
{
|
||||||
|
max_connect = it->second.GetInfo().max_connect;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ar(max_connect);
|
||||||
}
|
}
|
||||||
|
|
||||||
error_code cellKbInit(ppu_thread& ppu, u32 max_connect)
|
error_code cellKbInit(ppu_thread& ppu, u32 max_connect)
|
||||||
@ -79,7 +93,9 @@ error_code cellKbInit(ppu_thread& ppu, u32 max_connect)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sys_config_start(ppu);
|
sys_config_start(ppu);
|
||||||
handler.Init(std::min(max_connect, 7u));
|
|
||||||
|
std::lock_guard<std::mutex> lock(handler.m_mutex);
|
||||||
|
handler.AddConsumer(keyboard_consumer::identifier::cellKb, std::min(max_connect, 7u));
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
@ -95,6 +111,11 @@ error_code cellKbEnd(ppu_thread& ppu)
|
|||||||
if (!init)
|
if (!init)
|
||||||
return CELL_KB_ERROR_UNINITIALIZED;
|
return CELL_KB_ERROR_UNINITIALIZED;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(handler.m_mutex);
|
||||||
|
handler.RemoveConsumer(keyboard_consumer::identifier::cellKb);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
sys_config_stop(ppu);
|
sys_config_stop(ppu);
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
@ -116,12 +137,13 @@ error_code cellKbClearBuf(u32 port_no)
|
|||||||
|
|
||||||
std::lock_guard<std::mutex> lock(handler.m_mutex);
|
std::lock_guard<std::mutex> lock(handler.m_mutex);
|
||||||
|
|
||||||
const KbInfo& current_info = handler.GetInfo();
|
keyboard_consumer& consumer = handler.GetConsumer(keyboard_consumer::identifier::cellKb);
|
||||||
|
const KbInfo& current_info = consumer.GetInfo();
|
||||||
|
|
||||||
if (port_no >= handler.GetKeyboards().size() || current_info.status[port_no] != CELL_KB_STATUS_CONNECTED)
|
if (port_no >= consumer.GetKeyboards().size() || current_info.status[port_no] != CELL_KB_STATUS_CONNECTED)
|
||||||
return not_an_error(CELL_KB_ERROR_NO_DEVICE);
|
return not_an_error(CELL_KB_ERROR_NO_DEVICE);
|
||||||
|
|
||||||
KbData& current_data = handler.GetData(port_no);
|
KbData& current_data = consumer.GetData(port_no);
|
||||||
current_data.len = 0;
|
current_data.len = 0;
|
||||||
current_data.led = 0;
|
current_data.led = 0;
|
||||||
current_data.mkey = 0;
|
current_data.mkey = 0;
|
||||||
@ -298,8 +320,9 @@ error_code cellKbGetInfo(vm::ptr<CellKbInfo> info)
|
|||||||
std::memset(info.get_ptr(), 0, info.size());
|
std::memset(info.get_ptr(), 0, info.size());
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(handler.m_mutex);
|
std::lock_guard<std::mutex> lock(handler.m_mutex);
|
||||||
|
keyboard_consumer& consumer = handler.GetConsumer(keyboard_consumer::identifier::cellKb);
|
||||||
|
|
||||||
const KbInfo& current_info = handler.GetInfo();
|
const KbInfo& current_info = consumer.GetInfo();
|
||||||
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;
|
||||||
@ -327,13 +350,13 @@ error_code cellKbRead(u32 port_no, vm::ptr<CellKbData> data)
|
|||||||
return CELL_KB_ERROR_INVALID_PARAMETER;
|
return CELL_KB_ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(handler.m_mutex);
|
std::lock_guard<std::mutex> lock(handler.m_mutex);
|
||||||
|
keyboard_consumer& consumer = handler.GetConsumer(keyboard_consumer::identifier::cellKb);
|
||||||
|
const KbInfo& current_info = consumer.GetInfo();
|
||||||
|
|
||||||
const KbInfo& current_info = handler.GetInfo();
|
if (port_no >= consumer.GetKeyboards().size() || current_info.status[port_no] != CELL_KB_STATUS_CONNECTED)
|
||||||
|
|
||||||
if (port_no >= handler.GetKeyboards().size() || current_info.status[port_no] != CELL_KB_STATUS_CONNECTED)
|
|
||||||
return not_an_error(CELL_KB_ERROR_NO_DEVICE);
|
return not_an_error(CELL_KB_ERROR_NO_DEVICE);
|
||||||
|
|
||||||
KbData& current_data = handler.GetData(port_no);
|
KbData& current_data = consumer.GetData(port_no);
|
||||||
|
|
||||||
if (current_info.is_null_handler || (current_info.info & CELL_KB_INFO_INTERCEPTED) || !is_input_allowed())
|
if (current_info.is_null_handler || (current_info.info & CELL_KB_INFO_INTERCEPTED) || !is_input_allowed())
|
||||||
{
|
{
|
||||||
@ -355,7 +378,7 @@ error_code cellKbRead(u32 port_no, vm::ptr<CellKbData> data)
|
|||||||
data->keycode[i] = current_data.buttons[i].m_keyCode;
|
data->keycode[i] = current_data.buttons[i].m_keyCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
KbConfig& current_config = handler.GetConfig(port_no);
|
KbConfig& current_config = consumer.GetConfig(port_no);
|
||||||
|
|
||||||
// For single character mode to work properly we need to "flush" the buffer after reading or else we'll constantly get the same key presses with each call.
|
// For single character mode to work properly we need to "flush" the buffer after reading or else we'll constantly get the same key presses with each call.
|
||||||
// Actual key repeats are handled by adding a new key code to the buffer periodically. Key releases are handled in a similar fashion.
|
// Actual key repeats are handled by adding a new key code to the buffer periodically. Key releases are handled in a similar fashion.
|
||||||
@ -383,12 +406,13 @@ error_code cellKbSetCodeType(u32 port_no, u32 type)
|
|||||||
if (port_no >= CELL_KB_MAX_KEYBOARDS || type > CELL_KB_CODETYPE_ASCII)
|
if (port_no >= CELL_KB_MAX_KEYBOARDS || type > CELL_KB_CODETYPE_ASCII)
|
||||||
return CELL_KB_ERROR_INVALID_PARAMETER;
|
return CELL_KB_ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
if (port_no >= handler.GetKeyboards().size())
|
std::lock_guard<std::mutex> lock(handler.m_mutex);
|
||||||
|
keyboard_consumer& consumer = handler.GetConsumer(keyboard_consumer::identifier::cellKb);
|
||||||
|
|
||||||
|
if (port_no >= consumer.GetKeyboards().size())
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(handler.m_mutex);
|
KbConfig& current_config = consumer.GetConfig(port_no);
|
||||||
|
|
||||||
KbConfig& current_config = handler.GetConfig(port_no);
|
|
||||||
current_config.code_type = type;
|
current_config.code_type = type;
|
||||||
|
|
||||||
// can also return CELL_KB_ERROR_SYS_SETTING_FAILED
|
// can also return CELL_KB_ERROR_SYS_SETTING_FAILED
|
||||||
@ -413,12 +437,13 @@ error_code cellKbSetLEDStatus(u32 port_no, u8 led)
|
|||||||
if (led > 7)
|
if (led > 7)
|
||||||
return CELL_KB_ERROR_SYS_SETTING_FAILED;
|
return CELL_KB_ERROR_SYS_SETTING_FAILED;
|
||||||
|
|
||||||
if (port_no >= handler.GetKeyboards().size() || handler.GetInfo().status[port_no] != CELL_KB_STATUS_CONNECTED)
|
std::lock_guard<std::mutex> lock(handler.m_mutex);
|
||||||
|
keyboard_consumer& consumer = handler.GetConsumer(keyboard_consumer::identifier::cellKb);
|
||||||
|
|
||||||
|
if (port_no >= consumer.GetKeyboards().size() || consumer.GetInfo().status[port_no] != CELL_KB_STATUS_CONNECTED)
|
||||||
return CELL_KB_ERROR_FATAL;
|
return CELL_KB_ERROR_FATAL;
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(handler.m_mutex);
|
KbData& current_data = consumer.GetData(port_no);
|
||||||
|
|
||||||
KbData& current_data = handler.GetData(port_no);
|
|
||||||
current_data.led = static_cast<u32>(led);
|
current_data.led = static_cast<u32>(led);
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
@ -438,16 +463,17 @@ error_code cellKbSetReadMode(u32 port_no, u32 rmode)
|
|||||||
if (port_no >= CELL_KB_MAX_KEYBOARDS || rmode > CELL_KB_RMODE_PACKET)
|
if (port_no >= CELL_KB_MAX_KEYBOARDS || rmode > CELL_KB_RMODE_PACKET)
|
||||||
return CELL_KB_ERROR_INVALID_PARAMETER;
|
return CELL_KB_ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
if (port_no >= handler.GetKeyboards().size())
|
std::lock_guard<std::mutex> lock(handler.m_mutex);
|
||||||
|
keyboard_consumer& consumer = handler.GetConsumer(keyboard_consumer::identifier::cellKb);
|
||||||
|
|
||||||
|
if (port_no >= consumer.GetKeyboards().size())
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(handler.m_mutex);
|
KbConfig& current_config = consumer.GetConfig(port_no);
|
||||||
|
|
||||||
KbConfig& current_config = handler.GetConfig(port_no);
|
|
||||||
current_config.read_mode = rmode;
|
current_config.read_mode = rmode;
|
||||||
|
|
||||||
// Key repeat must be disabled in packet mode. But let's just always enable it otherwise.
|
// Key repeat must be disabled in packet mode. But let's just always enable it otherwise.
|
||||||
Keyboard& keyboard = handler.GetKeyboards()[port_no];
|
Keyboard& keyboard = consumer.GetKeyboards()[port_no];
|
||||||
keyboard.m_key_repeat = rmode != CELL_KB_RMODE_PACKET;
|
keyboard.m_key_repeat = rmode != CELL_KB_RMODE_PACKET;
|
||||||
|
|
||||||
// can also return CELL_KB_ERROR_SYS_SETTING_FAILED
|
// can also return CELL_KB_ERROR_SYS_SETTING_FAILED
|
||||||
@ -471,16 +497,18 @@ error_code cellKbGetConfiguration(u32 port_no, vm::ptr<CellKbConfig> config)
|
|||||||
|
|
||||||
std::lock_guard<std::mutex> lock(handler.m_mutex);
|
std::lock_guard<std::mutex> lock(handler.m_mutex);
|
||||||
|
|
||||||
const KbInfo& current_info = handler.GetInfo();
|
keyboard_consumer& consumer = handler.GetConsumer(keyboard_consumer::identifier::cellKb);
|
||||||
|
|
||||||
if (port_no >= handler.GetKeyboards().size() || current_info.status[port_no] != CELL_KB_STATUS_CONNECTED)
|
const KbInfo& current_info = consumer.GetInfo();
|
||||||
|
|
||||||
|
if (port_no >= consumer.GetKeyboards().size() || current_info.status[port_no] != CELL_KB_STATUS_CONNECTED)
|
||||||
return not_an_error(CELL_KB_ERROR_NO_DEVICE);
|
return not_an_error(CELL_KB_ERROR_NO_DEVICE);
|
||||||
|
|
||||||
// tests show that config is checked only after the device's status
|
// tests show that config is checked only after the device's status
|
||||||
if (!config)
|
if (!config)
|
||||||
return CELL_KB_ERROR_INVALID_PARAMETER;
|
return CELL_KB_ERROR_INVALID_PARAMETER;
|
||||||
|
|
||||||
const KbConfig& current_config = handler.GetConfig(port_no);
|
const KbConfig& current_config = consumer.GetConfig(port_no);
|
||||||
config->arrange = current_config.arrange;
|
config->arrange = current_config.arrange;
|
||||||
config->read_mode = current_config.read_mode;
|
config->read_mode = current_config.read_mode;
|
||||||
config->code_type = current_config.code_type;
|
config->code_type = current_config.code_type;
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
#include "KeyboardHandler.h"
|
#include "KeyboardHandler.h"
|
||||||
#include "Utilities/StrUtil.h"
|
#include "Utilities/StrUtil.h"
|
||||||
|
|
||||||
|
LOG_CHANNEL(input_log, "Input");
|
||||||
|
|
||||||
template <>
|
template <>
|
||||||
void fmt_class_string<CellKbMappingType>::format(std::string& out, u64 arg)
|
void fmt_class_string<CellKbMappingType>::format(std::string& out, u64 arg)
|
||||||
{
|
{
|
||||||
@ -40,12 +42,85 @@ void fmt_class_string<CellKbMappingType>::format(std::string& out, u64 arg)
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
void KeyboardHandlerBase::Key(u32 code, bool pressed, const std::u32string& key)
|
template <>
|
||||||
|
void fmt_class_string<keyboard_consumer::identifier>::format(std::string& out, u64 arg)
|
||||||
{
|
{
|
||||||
|
format_enum(out, arg, [](keyboard_consumer::identifier value)
|
||||||
|
{
|
||||||
|
switch (value)
|
||||||
|
{
|
||||||
|
STR_CASE(keyboard_consumer::identifier::unknown);
|
||||||
|
STR_CASE(keyboard_consumer::identifier::overlays);
|
||||||
|
STR_CASE(keyboard_consumer::identifier::cellKb);
|
||||||
|
}
|
||||||
|
|
||||||
|
return unknown;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
keyboard_consumer& KeyboardHandlerBase::AddConsumer(keyboard_consumer::identifier id, u32 max_connect)
|
||||||
|
{
|
||||||
|
auto it = m_consumers.find(id);
|
||||||
|
if (it == m_consumers.end())
|
||||||
|
{
|
||||||
|
input_log.notice("Adding keyboard consumer with id %s.", id);
|
||||||
|
keyboard_consumer& consumer = m_consumers[id];
|
||||||
|
consumer = keyboard_consumer(id);
|
||||||
|
Init(consumer, max_connect);
|
||||||
|
return consumer;
|
||||||
|
}
|
||||||
|
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
keyboard_consumer& KeyboardHandlerBase::GetConsumer(keyboard_consumer::identifier id)
|
||||||
|
{
|
||||||
|
auto it = m_consumers.find(id);
|
||||||
|
if (it == m_consumers.end())
|
||||||
|
{
|
||||||
|
fmt::throw_exception("No keyboard consumer with id %s", id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return it->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
void KeyboardHandlerBase::RemoveConsumer(keyboard_consumer::identifier id)
|
||||||
|
{
|
||||||
|
auto it = m_consumers.find(id);
|
||||||
|
if (it != m_consumers.end())
|
||||||
|
{
|
||||||
|
input_log.notice("Removing keyboard consumer with id %s.", id);
|
||||||
|
m_consumers.erase(id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool KeyboardHandlerBase::HandleKey(u32 code, bool pressed, bool is_auto_repeat, const std::u32string& key)
|
||||||
|
{
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
|
for (auto& [id, consumer] : m_consumers)
|
||||||
|
{
|
||||||
|
consumed |= consumer.ConsumeKey(code, pressed, is_auto_repeat, key);
|
||||||
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool keyboard_consumer::ConsumeKey(u32 code, bool pressed, bool is_auto_repeat, const std::u32string& key)
|
||||||
|
{
|
||||||
|
bool consumed = false;
|
||||||
|
|
||||||
for (Keyboard& keyboard : m_keyboards)
|
for (Keyboard& keyboard : m_keyboards)
|
||||||
{
|
{
|
||||||
|
if (is_auto_repeat && !keyboard.m_key_repeat)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
consumed = true;
|
||||||
|
|
||||||
KbData& data = keyboard.m_data;
|
KbData& data = keyboard.m_data;
|
||||||
const KbConfig& config = keyboard.m_config;
|
const KbConfig& config = keyboard.m_config;
|
||||||
|
|
||||||
@ -163,9 +238,11 @@ void KeyboardHandlerBase::Key(u32 code, bool pressed, const std::u32string& key)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return consumed;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool KeyboardHandlerBase::IsMetaKey(u32 code)
|
bool keyboard_consumer::IsMetaKey(u32 code)
|
||||||
{
|
{
|
||||||
return code == Key_Control
|
return code == Key_Control
|
||||||
|| code == Key_Shift
|
|| code == Key_Shift
|
||||||
@ -178,6 +255,14 @@ void KeyboardHandlerBase::SetIntercepted(bool intercepted)
|
|||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
|
|
||||||
|
for (auto& [id, consumer] : m_consumers)
|
||||||
|
{
|
||||||
|
consumer.SetIntercepted(intercepted);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyboard_consumer::SetIntercepted(bool intercepted)
|
||||||
|
{
|
||||||
m_info.info = intercepted ? CELL_KB_INFO_INTERCEPTED : 0;
|
m_info.info = intercepted ? CELL_KB_INFO_INTERCEPTED : 0;
|
||||||
|
|
||||||
if (intercepted)
|
if (intercepted)
|
||||||
@ -196,17 +281,25 @@ void KeyboardHandlerBase::SetIntercepted(bool intercepted)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void KeyboardHandlerBase::ReleaseAllKeys()
|
void KeyboardHandlerBase::ReleaseAllKeys()
|
||||||
|
{
|
||||||
|
for (auto& [id, consumer] : m_consumers)
|
||||||
|
{
|
||||||
|
consumer.ReleaseAllKeys();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void keyboard_consumer::ReleaseAllKeys()
|
||||||
{
|
{
|
||||||
for (Keyboard& keyboard : m_keyboards)
|
for (Keyboard& keyboard : m_keyboards)
|
||||||
{
|
{
|
||||||
for (const auto& [key_code, button] : keyboard.m_keys)
|
for (const auto& [key_code, button] : keyboard.m_keys)
|
||||||
{
|
{
|
||||||
Key(button.m_keyCode, false, {});
|
ConsumeKey(button.m_keyCode, false, false, {});
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const std::u32string& key : keyboard.m_extra_data.pressed_keys)
|
for (const std::u32string& key : keyboard.m_extra_data.pressed_keys)
|
||||||
{
|
{
|
||||||
Key(CELL_KEYC_NO_EVENT, false, key);
|
ConsumeKey(CELL_KEYC_NO_EVENT, false, false, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
keyboard.m_extra_data.pressed_keys.clear();
|
keyboard.m_extra_data.pressed_keys.clear();
|
||||||
|
@ -75,21 +75,20 @@ struct Keyboard
|
|||||||
std::unordered_map<u32, KbButton> m_keys;
|
std::unordered_map<u32, KbButton> m_keys;
|
||||||
};
|
};
|
||||||
|
|
||||||
class KeyboardHandlerBase
|
class keyboard_consumer
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
std::mutex m_mutex;
|
enum class identifier
|
||||||
|
{
|
||||||
|
unknown,
|
||||||
|
overlays,
|
||||||
|
cellKb,
|
||||||
|
};
|
||||||
|
|
||||||
virtual void Init(const u32 max_connect) = 0;
|
keyboard_consumer() {}
|
||||||
|
keyboard_consumer(identifier id) : m_id(id) {}
|
||||||
|
|
||||||
virtual ~KeyboardHandlerBase() = default;
|
bool ConsumeKey(u32 code, bool pressed, bool is_auto_repeat, const std::u32string& key);
|
||||||
KeyboardHandlerBase(utils::serial* ar);
|
|
||||||
KeyboardHandlerBase(utils::serial& ar) : KeyboardHandlerBase(&ar) {}
|
|
||||||
void save(utils::serial& ar);
|
|
||||||
|
|
||||||
SAVESTATE_INIT_POS(19);
|
|
||||||
|
|
||||||
void Key(u32 code, bool pressed, const std::u32string& key);
|
|
||||||
void SetIntercepted(bool intercepted);
|
void SetIntercepted(bool intercepted);
|
||||||
|
|
||||||
static bool IsMetaKey(u32 code);
|
static bool IsMetaKey(u32 code);
|
||||||
@ -99,12 +98,41 @@ public:
|
|||||||
KbData& GetData(const u32 keyboard) { return m_keyboards[keyboard].m_data; }
|
KbData& GetData(const u32 keyboard) { return m_keyboards[keyboard].m_data; }
|
||||||
KbExtraData& GetExtraData(const u32 keyboard) { return m_keyboards[keyboard].m_extra_data; }
|
KbExtraData& GetExtraData(const u32 keyboard) { return m_keyboards[keyboard].m_extra_data; }
|
||||||
KbConfig& GetConfig(const u32 keyboard) { return m_keyboards[keyboard].m_config; }
|
KbConfig& GetConfig(const u32 keyboard) { return m_keyboards[keyboard].m_config; }
|
||||||
|
identifier id() const { return m_id; }
|
||||||
|
|
||||||
|
void ReleaseAllKeys();
|
||||||
|
|
||||||
|
protected:
|
||||||
|
identifier m_id = identifier::unknown;
|
||||||
|
KbInfo m_info{};
|
||||||
|
std::vector<Keyboard> m_keyboards;
|
||||||
|
};
|
||||||
|
|
||||||
|
class KeyboardHandlerBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::mutex m_mutex;
|
||||||
|
|
||||||
|
virtual void Init(keyboard_consumer& consumer, const u32 max_connect) = 0;
|
||||||
|
|
||||||
|
virtual ~KeyboardHandlerBase() = default;
|
||||||
|
KeyboardHandlerBase(utils::serial* ar);
|
||||||
|
KeyboardHandlerBase(utils::serial& ar) : KeyboardHandlerBase(&ar) {}
|
||||||
|
void save(utils::serial& ar);
|
||||||
|
|
||||||
|
SAVESTATE_INIT_POS(19);
|
||||||
|
|
||||||
|
keyboard_consumer& AddConsumer(keyboard_consumer::identifier id, u32 max_connect);
|
||||||
|
keyboard_consumer& GetConsumer(keyboard_consumer::identifier id);
|
||||||
|
void RemoveConsumer(keyboard_consumer::identifier id);
|
||||||
|
|
||||||
|
bool HandleKey(u32 code, bool pressed, bool is_auto_repeat, const std::u32string& key);
|
||||||
|
void SetIntercepted(bool intercepted);
|
||||||
|
|
||||||
stx::init_mutex init;
|
stx::init_mutex init;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
void ReleaseAllKeys();
|
void ReleaseAllKeys();
|
||||||
|
|
||||||
KbInfo m_info{};
|
std::unordered_map<keyboard_consumer::identifier, keyboard_consumer> m_consumers;
|
||||||
std::vector<Keyboard> m_keyboards;
|
|
||||||
};
|
};
|
||||||
|
@ -7,15 +7,18 @@ class NullKeyboardHandler final : public KeyboardHandlerBase
|
|||||||
using KeyboardHandlerBase::KeyboardHandlerBase;
|
using KeyboardHandlerBase::KeyboardHandlerBase;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Init(const u32 max_connect) override
|
void Init(keyboard_consumer& consumer, const u32 max_connect) override
|
||||||
{
|
{
|
||||||
m_info = {};
|
KbInfo& info = consumer.GetInfo();
|
||||||
m_info.max_connect = max_connect;
|
std::vector<Keyboard>& keyboards = consumer.GetKeyboards();
|
||||||
m_info.is_null_handler = true;
|
|
||||||
m_keyboards.clear();
|
info = {};
|
||||||
|
info.max_connect = max_connect;
|
||||||
|
info.is_null_handler = true;
|
||||||
|
keyboards.clear();
|
||||||
for (u32 i = 0; i < max_connect; i++)
|
for (u32 i = 0; i < max_connect; i++)
|
||||||
{
|
{
|
||||||
m_keyboards.emplace_back(Keyboard());
|
keyboards.emplace_back(Keyboard());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -155,13 +155,17 @@ namespace rsx
|
|||||||
// Ignored if a keyboard pad handler is active in order to prevent double input.
|
// Ignored if a keyboard pad handler is active in order to prevent double input.
|
||||||
if (m_keyboard_input_enabled && !m_keyboard_pad_handler_active && input::g_keyboards_intercepted)
|
if (m_keyboard_input_enabled && !m_keyboard_pad_handler_active && input::g_keyboards_intercepted)
|
||||||
{
|
{
|
||||||
auto& handler = g_fxo->get<KeyboardHandlerBase>();
|
auto& kb_handler = g_fxo->get<KeyboardHandlerBase>();
|
||||||
std::lock_guard<std::mutex> lock(handler.m_mutex);
|
std::lock_guard<std::mutex> lock(kb_handler.m_mutex);
|
||||||
|
|
||||||
if (!handler.GetKeyboards().empty() && handler.GetInfo().status[0] == CELL_KB_STATUS_CONNECTED)
|
// Add and get consumer
|
||||||
|
keyboard_consumer& kb_consumer = kb_handler.AddConsumer(keyboard_consumer::identifier::overlays, 1);
|
||||||
|
std::vector<Keyboard>& keyboards = kb_consumer.GetKeyboards();
|
||||||
|
|
||||||
|
if (!keyboards.empty() && kb_consumer.GetInfo().status[0] == CELL_KB_STATUS_CONNECTED)
|
||||||
{
|
{
|
||||||
KbData& current_data = handler.GetData(0);
|
KbData& current_data = kb_consumer.GetData(0);
|
||||||
KbExtraData& extra_data = handler.GetExtraData(0);
|
KbExtraData& extra_data = kb_consumer.GetExtraData(0);
|
||||||
|
|
||||||
if (current_data.len > 0 || !extra_data.pressed_keys.empty())
|
if (current_data.len > 0 || !extra_data.pressed_keys.empty())
|
||||||
{
|
{
|
||||||
@ -185,16 +189,6 @@ namespace rsx
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (g_cfg.io.keyboard != keyboard_handler::null)
|
|
||||||
{
|
|
||||||
// Workaround if cellKb did not init the keyboard handler.
|
|
||||||
handler.Init(1);
|
|
||||||
|
|
||||||
// Enable key repeat
|
|
||||||
std::vector<Keyboard>& keyboards = handler.GetKeyboards();
|
|
||||||
ensure(!keyboards.empty());
|
|
||||||
::at32(keyboards, 0).m_key_repeat = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get gamepad input
|
// Get gamepad input
|
||||||
@ -202,14 +196,9 @@ namespace rsx
|
|||||||
const auto handler = pad::get_current_handler();
|
const auto handler = pad::get_current_handler();
|
||||||
const PadInfo& rinfo = handler->GetInfo();
|
const PadInfo& rinfo = handler->GetInfo();
|
||||||
|
|
||||||
if (!rinfo.now_connect || !input::g_pads_intercepted)
|
const bool ignore_gamepad_input = (!rinfo.now_connect || !input::g_pads_intercepted);
|
||||||
{
|
|
||||||
m_keyboard_pad_handler_active = false;
|
|
||||||
refresh();
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool keyboard_pad_handler_active = false;
|
m_keyboard_pad_handler_active = false;
|
||||||
|
|
||||||
int pad_index = -1;
|
int pad_index = -1;
|
||||||
for (const auto& pad : handler->GetPads())
|
for (const auto& pad : handler->GetPads())
|
||||||
@ -244,6 +233,16 @@ namespace rsx
|
|||||||
m_keyboard_pad_handler_active = true;
|
m_keyboard_pad_handler_active = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (ignore_gamepad_input)
|
||||||
|
{
|
||||||
|
if (m_keyboard_pad_handler_active)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for (const Button& button : pad->m_buttons)
|
for (const Button& button : pad->m_buttons)
|
||||||
{
|
{
|
||||||
pad_button button_id = pad_button::pad_button_max_enum;
|
pad_button button_id = pad_button::pad_button_max_enum;
|
||||||
@ -362,11 +361,16 @@ namespace rsx
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_keyboard_pad_handler_active = keyboard_pad_handler_active;
|
|
||||||
|
|
||||||
refresh();
|
refresh();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Remove keyboard consumer. We don't need it anymore.
|
||||||
|
{
|
||||||
|
auto& kb_handler = g_fxo->get<KeyboardHandlerBase>();
|
||||||
|
std::lock_guard<std::mutex> lock(kb_handler.m_mutex);
|
||||||
|
kb_handler.RemoveConsumer(keyboard_consumer::identifier::overlays);
|
||||||
|
}
|
||||||
|
|
||||||
// Disable pad interception since this user interface has to be interactive.
|
// Disable pad interception since this user interface has to be interactive.
|
||||||
// Non-interactive user intefaces handle this in close in order to prevent a g_pad_mutex deadlock.
|
// Non-interactive user intefaces handle this in close in order to prevent a g_pad_mutex deadlock.
|
||||||
if (m_stop_pad_interception)
|
if (m_stop_pad_interception)
|
||||||
|
@ -11,26 +11,34 @@
|
|||||||
|
|
||||||
LOG_CHANNEL(input_log, "Input");
|
LOG_CHANNEL(input_log, "Input");
|
||||||
|
|
||||||
void basic_keyboard_handler::Init(const u32 max_connect)
|
void basic_keyboard_handler::Init(keyboard_consumer& consumer, const u32 max_connect)
|
||||||
{
|
{
|
||||||
m_keyboards.clear();
|
KbInfo& info = consumer.GetInfo();
|
||||||
m_info = {};
|
std::vector<Keyboard>& keyboards = consumer.GetKeyboards();
|
||||||
|
|
||||||
|
info = {};
|
||||||
|
keyboards.clear();
|
||||||
|
|
||||||
for (u32 i = 0; i < max_connect; i++)
|
for (u32 i = 0; i < max_connect; i++)
|
||||||
{
|
{
|
||||||
Keyboard kb{};
|
Keyboard kb{};
|
||||||
|
|
||||||
kb.m_config.arrange = g_cfg.sys.keyboard_type;
|
kb.m_config.arrange = g_cfg.sys.keyboard_type;
|
||||||
|
|
||||||
m_keyboards.emplace_back(kb);
|
if (consumer.id() == keyboard_consumer::identifier::overlays)
|
||||||
|
{
|
||||||
|
// Enable key repeat
|
||||||
|
kb.m_key_repeat = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
LoadSettings(kb);
|
||||||
|
|
||||||
|
keyboards.emplace_back(kb);
|
||||||
}
|
}
|
||||||
|
|
||||||
LoadSettings();
|
info.max_connect = max_connect;
|
||||||
|
info.now_connect = std::min(::size32(keyboards), max_connect);
|
||||||
m_info.max_connect = max_connect;
|
info.info = input::g_keyboards_intercepted ? CELL_KB_INFO_INTERCEPTED : 0; // Ownership of keyboard data: 0=Application, 1=System
|
||||||
m_info.now_connect = std::min(::size32(m_keyboards), max_connect);
|
info.status[0] = CELL_KB_STATUS_CONNECTED; // (TODO: Support for more keyboards)
|
||||||
m_info.info = input::g_keyboards_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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sets the target window for the event handler, and also installs an event filter on the target. */
|
/* Sets the target window for the event handler, and also installs an event filter on the target. */
|
||||||
@ -94,7 +102,7 @@ void basic_keyboard_handler::keyPressEvent(QKeyEvent* keyEvent)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_keyboards.empty() || (keyEvent->isAutoRepeat() && !m_keyboards[0].m_key_repeat))
|
if (m_consumers.empty())
|
||||||
{
|
{
|
||||||
keyEvent->ignore();
|
keyEvent->ignore();
|
||||||
return;
|
return;
|
||||||
@ -102,9 +110,9 @@ void basic_keyboard_handler::keyPressEvent(QKeyEvent* keyEvent)
|
|||||||
|
|
||||||
const int key = getUnmodifiedKey(keyEvent);
|
const int key = getUnmodifiedKey(keyEvent);
|
||||||
|
|
||||||
if (key >= 0)
|
if (key < 0 || !HandleKey(static_cast<u32>(key), true, keyEvent->isAutoRepeat(), keyEvent->text().toStdU32String()))
|
||||||
{
|
{
|
||||||
Key(static_cast<u32>(key), true, keyEvent->text().toStdU32String());
|
keyEvent->ignore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,7 +123,7 @@ void basic_keyboard_handler::keyReleaseEvent(QKeyEvent* keyEvent)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_keyboards.empty() || (keyEvent->isAutoRepeat() && !m_keyboards[0].m_key_repeat))
|
if (m_consumers.empty())
|
||||||
{
|
{
|
||||||
keyEvent->ignore();
|
keyEvent->ignore();
|
||||||
return;
|
return;
|
||||||
@ -123,9 +131,9 @@ void basic_keyboard_handler::keyReleaseEvent(QKeyEvent* keyEvent)
|
|||||||
|
|
||||||
const int key = getUnmodifiedKey(keyEvent);
|
const int key = getUnmodifiedKey(keyEvent);
|
||||||
|
|
||||||
if (key >= 0)
|
if (key < 0 || !HandleKey(static_cast<u32>(key), false, keyEvent->isAutoRepeat(), keyEvent->text().toStdU32String()))
|
||||||
{
|
{
|
||||||
Key(static_cast<u32>(key), false, keyEvent->text().toStdU32String());
|
keyEvent->ignore();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -166,15 +174,8 @@ s32 basic_keyboard_handler::getUnmodifiedKey(QKeyEvent* keyEvent)
|
|||||||
return static_cast<s32>(raw_key);
|
return static_cast<s32>(raw_key);
|
||||||
}
|
}
|
||||||
|
|
||||||
void basic_keyboard_handler::LoadSettings()
|
void basic_keyboard_handler::LoadSettings(Keyboard& keyboard)
|
||||||
{
|
{
|
||||||
if (m_keyboards.empty())
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Keyboard& keyboard = m_keyboards[0];
|
|
||||||
|
|
||||||
std::vector<KbButton> buttons;
|
std::vector<KbButton> buttons;
|
||||||
|
|
||||||
// Meta Keys
|
// Meta Keys
|
||||||
@ -194,7 +195,7 @@ void basic_keyboard_handler::LoadSettings()
|
|||||||
//buttons.emplace_back(, CELL_KEYC_E_UNDEF);
|
//buttons.emplace_back(, CELL_KEYC_E_UNDEF);
|
||||||
buttons.emplace_back(Qt::Key_Escape, CELL_KEYC_ESCAPE);
|
buttons.emplace_back(Qt::Key_Escape, CELL_KEYC_ESCAPE);
|
||||||
buttons.emplace_back(Qt::Key_Kanji, CELL_KEYC_106_KANJI);
|
buttons.emplace_back(Qt::Key_Kanji, CELL_KEYC_106_KANJI);
|
||||||
//buttons.emplace_back(Qt::Key_CapsLock, CELL_KEYC_CAPS_LOCK);
|
buttons.emplace_back(Qt::Key_CapsLock, CELL_KEYC_CAPS_LOCK);
|
||||||
buttons.emplace_back(Qt::Key_F1, CELL_KEYC_F1);
|
buttons.emplace_back(Qt::Key_F1, CELL_KEYC_F1);
|
||||||
buttons.emplace_back(Qt::Key_F2, CELL_KEYC_F2);
|
buttons.emplace_back(Qt::Key_F2, CELL_KEYC_F2);
|
||||||
buttons.emplace_back(Qt::Key_F3, CELL_KEYC_F3);
|
buttons.emplace_back(Qt::Key_F3, CELL_KEYC_F3);
|
||||||
@ -221,7 +222,7 @@ void basic_keyboard_handler::LoadSettings()
|
|||||||
buttons.emplace_back(Qt::Key_Down, CELL_KEYC_DOWN_ARROW);
|
buttons.emplace_back(Qt::Key_Down, CELL_KEYC_DOWN_ARROW);
|
||||||
buttons.emplace_back(Qt::Key_Up, CELL_KEYC_UP_ARROW);
|
buttons.emplace_back(Qt::Key_Up, CELL_KEYC_UP_ARROW);
|
||||||
//buttons.emplace_back(WXK_NUMLOCK, CELL_KEYC_NUM_LOCK);
|
//buttons.emplace_back(WXK_NUMLOCK, CELL_KEYC_NUM_LOCK);
|
||||||
//buttons.emplace_back(, CELL_KEYC_APPLICATION);
|
buttons.emplace_back(Qt::Key_Meta, CELL_KEYC_APPLICATION);
|
||||||
buttons.emplace_back(Qt::Key_Kana_Shift, CELL_KEYC_KANA); // maybe Key_Kana_Lock
|
buttons.emplace_back(Qt::Key_Kana_Shift, CELL_KEYC_KANA); // maybe Key_Kana_Lock
|
||||||
buttons.emplace_back(Qt::Key_Henkan, CELL_KEYC_HENKAN);
|
buttons.emplace_back(Qt::Key_Henkan, CELL_KEYC_HENKAN);
|
||||||
buttons.emplace_back(Qt::Key_Muhenkan, CELL_KEYC_MUHENKAN);
|
buttons.emplace_back(Qt::Key_Muhenkan, CELL_KEYC_MUHENKAN);
|
||||||
|
@ -11,14 +11,16 @@ class basic_keyboard_handler final : public KeyboardHandlerBase, public QObject
|
|||||||
using KeyboardHandlerBase::KeyboardHandlerBase;
|
using KeyboardHandlerBase::KeyboardHandlerBase;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
void Init(const u32 max_connect) override;
|
void Init(keyboard_consumer& consumer, const u32 max_connect) override;
|
||||||
|
|
||||||
void SetTargetWindow(QWindow* target);
|
void SetTargetWindow(QWindow* target);
|
||||||
bool eventFilter(QObject* watched, QEvent* event) override;
|
bool eventFilter(QObject* watched, QEvent* event) override;
|
||||||
void keyPressEvent(QKeyEvent* event);
|
void keyPressEvent(QKeyEvent* event);
|
||||||
void keyReleaseEvent(QKeyEvent* event);
|
void keyReleaseEvent(QKeyEvent* event);
|
||||||
static s32 getUnmodifiedKey(QKeyEvent* event);
|
static s32 getUnmodifiedKey(QKeyEvent* event);
|
||||||
void LoadSettings();
|
|
||||||
private:
|
private:
|
||||||
|
void LoadSettings(Keyboard& keyboard);
|
||||||
|
|
||||||
QWindow* m_target = nullptr;
|
QWindow* m_target = nullptr;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user