mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 19:45:20 +00:00
Qt/input: allow keypresses in raw mouse handler
This commit is contained in:
parent
78a661db79
commit
72da20f5e1
7 changed files with 179 additions and 21 deletions
|
@ -43,6 +43,15 @@ std::string raw_mouse_config::get_button_name(std::string_view value)
|
|||
return std::string(value);
|
||||
}
|
||||
|
||||
if (value.starts_with(key_prefix))
|
||||
{
|
||||
s64 scan_code{};
|
||||
if (try_to_int64(&scan_code, value.substr(key_prefix.size()), s32{smin}, s32{smax}))
|
||||
{
|
||||
return get_key_name(static_cast<s32>(scan_code));
|
||||
}
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
|
@ -58,6 +67,22 @@ std::string raw_mouse_config::get_button_name(s32 button_code)
|
|||
return "";
|
||||
}
|
||||
|
||||
std::string raw_mouse_config::get_key_name(s32 scan_code)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
TCHAR name_buf[MAX_PATH] {};
|
||||
if (!GetKeyNameTextW(scan_code, name_buf, MAX_PATH))
|
||||
{
|
||||
cfg_log.error("raw_mouse_config: GetKeyNameText failed: %s", fmt::win_error{GetLastError(), nullptr});
|
||||
return {};
|
||||
}
|
||||
return wchar_to_utf8(name_buf);
|
||||
#else
|
||||
static_cast<void>(scan_code);
|
||||
return "";
|
||||
#endif
|
||||
}
|
||||
|
||||
raw_mice_config::raw_mice_config()
|
||||
{
|
||||
for (u32 i = 0; i < ::size32(players); i++)
|
||||
|
|
|
@ -42,8 +42,11 @@ public:
|
|||
cfg::string& get_button_by_index(int index);
|
||||
cfg::string& get_button(int code);
|
||||
|
||||
static constexpr std::string_view key_prefix = "Key ";
|
||||
|
||||
static std::string get_button_name(std::string_view value);
|
||||
static std::string get_button_name(s32 button_code);
|
||||
static std::string get_key_name(s32 scan_code);
|
||||
};
|
||||
|
||||
struct raw_mice_config : cfg::node
|
||||
|
|
|
@ -27,17 +27,17 @@ static inline void draw_overlay_cursor(u32 index, s32 x_pos, s32 y_pos, s32 x_ma
|
|||
[[maybe_unused]] static inline void draw_overlay_cursor(u32, s32, s32, s32, s32) {}
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
const std::unordered_map<int, raw_mouse::mouse_button> raw_mouse::btn_pairs =
|
||||
{
|
||||
{ 0, {}},
|
||||
{ RI_MOUSE_BUTTON_1_UP, mouse_button{ RI_MOUSE_BUTTON_1_DOWN, RI_MOUSE_BUTTON_1_UP }},
|
||||
{ RI_MOUSE_BUTTON_2_UP, mouse_button{ RI_MOUSE_BUTTON_2_DOWN, RI_MOUSE_BUTTON_2_UP }},
|
||||
{ RI_MOUSE_BUTTON_3_UP, mouse_button{ RI_MOUSE_BUTTON_3_DOWN, RI_MOUSE_BUTTON_3_UP }},
|
||||
{ RI_MOUSE_BUTTON_4_UP, mouse_button{ RI_MOUSE_BUTTON_4_DOWN, RI_MOUSE_BUTTON_4_UP }},
|
||||
{ RI_MOUSE_BUTTON_5_UP, mouse_button{ RI_MOUSE_BUTTON_5_DOWN, RI_MOUSE_BUTTON_5_UP }},
|
||||
};
|
||||
#ifdef _WIN32
|
||||
{ RI_MOUSE_BUTTON_1_UP, mouse_button{ RI_MOUSE_BUTTON_1_DOWN, RI_MOUSE_BUTTON_1_UP, 0, false }},
|
||||
{ RI_MOUSE_BUTTON_2_UP, mouse_button{ RI_MOUSE_BUTTON_2_DOWN, RI_MOUSE_BUTTON_2_UP, 0, false }},
|
||||
{ RI_MOUSE_BUTTON_3_UP, mouse_button{ RI_MOUSE_BUTTON_3_DOWN, RI_MOUSE_BUTTON_3_UP, 0, false }},
|
||||
{ RI_MOUSE_BUTTON_4_UP, mouse_button{ RI_MOUSE_BUTTON_4_DOWN, RI_MOUSE_BUTTON_4_UP, 0, false }},
|
||||
{ RI_MOUSE_BUTTON_5_UP, mouse_button{ RI_MOUSE_BUTTON_5_DOWN, RI_MOUSE_BUTTON_5_UP, 0, false }},
|
||||
#endif
|
||||
};
|
||||
|
||||
LOG_CHANNEL(input_log, "Input");
|
||||
|
||||
|
@ -89,12 +89,19 @@ raw_mouse::mouse_button raw_mouse::get_mouse_button(const cfg::string& button)
|
|||
{
|
||||
const std::string value = button.to_string();
|
||||
|
||||
#ifdef _WIN32
|
||||
if (const auto it = raw_mouse_button_map.find(value); it != raw_mouse_button_map.cend())
|
||||
{
|
||||
return ::at32(btn_pairs, it->second);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (value.starts_with(raw_mouse_config::key_prefix))
|
||||
{
|
||||
s64 scan_code{};
|
||||
if (try_to_int64(&scan_code, value.substr(raw_mouse_config::key_prefix.size()), s32{smin}, s32{smax}))
|
||||
{
|
||||
return mouse_button{ 0, 0, static_cast<s32>(scan_code), true };
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
@ -161,6 +168,8 @@ void raw_mouse::update_values(const RAWMOUSE& state)
|
|||
// Get mouse buttons
|
||||
for (const auto& [button, btn] : m_buttons)
|
||||
{
|
||||
if (btn.is_key) continue;
|
||||
|
||||
// Only update the value if either down or up flags are present
|
||||
if ((state.usButtonFlags & btn.down))
|
||||
{
|
||||
|
@ -240,6 +249,30 @@ void raw_mouse::update_values(const RAWMOUSE& state)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
void raw_mouse::update_values(s32 scan_code, bool pressed)
|
||||
{
|
||||
ensure(m_handler != nullptr);
|
||||
|
||||
if (std::exchange(m_reload_requested, false))
|
||||
{
|
||||
reload_config();
|
||||
}
|
||||
|
||||
if (m_handler->is_for_gui())
|
||||
{
|
||||
m_handler->key_press_callback(m_device_name, scan_code, pressed);
|
||||
return;
|
||||
}
|
||||
|
||||
// Get mouse buttons
|
||||
for (const auto& [button, btn] : m_buttons)
|
||||
{
|
||||
if (!btn.is_key || btn.scan_code != scan_code) return;
|
||||
|
||||
m_handler->Button(m_index, button, pressed);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
raw_mouse_handler::~raw_mouse_handler()
|
||||
|
@ -419,6 +452,12 @@ void raw_mouse_handler::register_raw_input_devices()
|
|||
.dwFlags = 0,
|
||||
.hwndTarget = mouse.window_handle()
|
||||
});
|
||||
raw_input_devices.push_back(RAWINPUTDEVICE {
|
||||
.usUsagePage = HID_USAGE_PAGE_GENERIC,
|
||||
.usUsage = HID_USAGE_GENERIC_KEYBOARD,
|
||||
.dwFlags = 0,
|
||||
.hwndTarget = mouse.window_handle()
|
||||
});
|
||||
|
||||
{
|
||||
std::lock_guard lock(g_registered_handlers_mutex);
|
||||
|
@ -459,6 +498,13 @@ void raw_mouse_handler::unregister_raw_input_devices() const
|
|||
.dwFlags = RIDEV_REMOVE,
|
||||
.hwndTarget = nullptr
|
||||
});
|
||||
raw_input_devices.push_back(RAWINPUTDEVICE {
|
||||
.usUsagePage = HID_USAGE_PAGE_GENERIC,
|
||||
.usUsage = HID_USAGE_GENERIC_KEYBOARD,
|
||||
.dwFlags = 0,
|
||||
.hwndTarget = nullptr
|
||||
});
|
||||
|
||||
if (!RegisterRawInputDevices(raw_input_devices.data(), ::size32(raw_input_devices), sizeof(RAWINPUTDEVICE)))
|
||||
{
|
||||
input_log.error("raw_mouse_handler: RegisterRawInputDevices (unregister) failed: %s", fmt::win_error{GetLastError(), nullptr});
|
||||
|
@ -566,7 +612,7 @@ void raw_mouse_handler::handle_native_event(const MSG& msg)
|
|||
return;
|
||||
}
|
||||
|
||||
if (msg.message != WM_INPUT)
|
||||
if (msg.message != WM_INPUT && msg.message != WM_KEYDOWN && msg.message != WM_KEYUP)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
@ -585,26 +631,64 @@ void raw_mouse_handler::handle_native_event(const MSG& msg)
|
|||
return;
|
||||
}
|
||||
|
||||
if ((raw_input.header.dwType == RIM_TYPEMOUSE || raw_input.header.dwType == RIM_TYPEKEYBOARD) &&
|
||||
g_cfg_raw_mouse.reload_requested.exchange(false))
|
||||
{
|
||||
std::lock_guard lock(m_raw_mutex);
|
||||
|
||||
for (auto& [handle, mouse] : m_raw_mice)
|
||||
{
|
||||
mouse.request_reload();
|
||||
}
|
||||
}
|
||||
|
||||
switch (raw_input.header.dwType)
|
||||
{
|
||||
case RIM_TYPEMOUSE:
|
||||
{
|
||||
std::lock_guard lock(m_raw_mutex);
|
||||
|
||||
if (g_cfg_raw_mouse.reload_requested.exchange(false))
|
||||
{
|
||||
for (auto& [handle, mouse] : m_raw_mice)
|
||||
{
|
||||
mouse.request_reload();
|
||||
}
|
||||
}
|
||||
|
||||
if (auto it = m_raw_mice.find(raw_input.header.hDevice); it != m_raw_mice.end())
|
||||
{
|
||||
it->second.update_values(raw_input.data.mouse);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case RIM_TYPEKEYBOARD:
|
||||
{
|
||||
const RAWKEYBOARD& keyboard = raw_input.data.keyboard;
|
||||
|
||||
// Ignore key overrun state and keys not mapped to any virtual key code
|
||||
if (keyboard.MakeCode == KEYBOARD_OVERRUN_MAKE_CODE || keyboard.VKey >= UCHAR_MAX)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
WORD scan_code;
|
||||
|
||||
if (keyboard.MakeCode)
|
||||
{
|
||||
// Compose the full scan code value with its extended byte
|
||||
scan_code = MAKEWORD(keyboard.MakeCode & 0x7f, ((keyboard.Flags & RI_KEY_E0) ? 0xe0 : ((keyboard.Flags & RI_KEY_E1) ? 0xe1 : 0x00)));
|
||||
}
|
||||
else
|
||||
{
|
||||
// Scan code value may be empty for some buttons (for example multimedia buttons)
|
||||
// Try to get the scan code from the virtual key code
|
||||
scan_code = LOWORD(MapVirtualKey(keyboard.VKey, MAPVK_VK_TO_VSC_EX));
|
||||
}
|
||||
|
||||
const LONG scan_code_extended = static_cast<LONG>(MAKELPARAM(0, (HIBYTE(scan_code) ? KF_EXTENDED : 0x00) | LOBYTE(scan_code)));
|
||||
const bool pressed = !(keyboard.Flags & RI_KEY_BREAK);
|
||||
|
||||
std::lock_guard lock(m_raw_mutex);
|
||||
|
||||
for (auto& [handle, mouse] : m_raw_mice)
|
||||
{
|
||||
mouse.update_values(scan_code_extended, pressed);
|
||||
}
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
|
|
|
@ -22,6 +22,7 @@ public:
|
|||
|
||||
#ifdef _WIN32
|
||||
void update_values(const RAWMOUSE& state);
|
||||
void update_values(s32 scan_code, bool pressed);
|
||||
#endif
|
||||
|
||||
const std::string& device_name() const { return m_device_name; }
|
||||
|
@ -34,11 +35,11 @@ private:
|
|||
{
|
||||
int down = 0;
|
||||
int up = 0;
|
||||
s32 scan_code = 0;
|
||||
bool is_key = false;
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
static const std::unordered_map<int, raw_mouse::mouse_button> btn_pairs;
|
||||
#endif
|
||||
|
||||
void reload_config();
|
||||
static mouse_button get_mouse_button(const cfg::string& button);
|
||||
|
@ -86,6 +87,19 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void set_key_press_callback(std::function<void(const std::string&, s32, bool)> cb)
|
||||
{
|
||||
m_key_press_callback = std::move(cb);
|
||||
}
|
||||
|
||||
void key_press_callback(const std::string& device_name, s32 scan_code, bool pressed)
|
||||
{
|
||||
if (m_key_press_callback)
|
||||
{
|
||||
m_key_press_callback(device_name, scan_code, pressed);
|
||||
}
|
||||
}
|
||||
|
||||
void update_devices();
|
||||
|
||||
#ifdef _WIN32
|
||||
|
@ -107,6 +121,7 @@ private:
|
|||
bool m_is_for_gui = false;
|
||||
std::map<void*, raw_mouse> m_raw_mice;
|
||||
std::function<void(const std::string&, s32, bool)> m_mouse_press_callback;
|
||||
std::function<void(const std::string&, s32, bool)> m_key_press_callback;
|
||||
|
||||
std::unique_ptr<named_thread<std::function<void()>>> m_thread;
|
||||
};
|
||||
|
|
|
@ -1187,7 +1187,7 @@ bool gui_application::native_event_filter::nativeEventFilter([[maybe_unused]] co
|
|||
|
||||
if (eventType == "windows_generic_MSG")
|
||||
{
|
||||
if (MSG* msg = static_cast<MSG*>(message); msg && msg->message == WM_INPUT)
|
||||
if (MSG* msg = static_cast<MSG*>(message); msg && (msg->message == WM_INPUT || msg->message == WM_KEYDOWN || msg->message == WM_KEYUP))
|
||||
{
|
||||
if (auto* handler = g_fxo->try_get<MouseHandlerBase>(); handler && handler->type == mouse_handler::raw)
|
||||
{
|
||||
|
|
|
@ -74,6 +74,10 @@ raw_mouse_settings_dialog::raw_mouse_settings_dialog(QWidget* parent)
|
|||
{
|
||||
mouse_press(device_name, button_code, pressed);
|
||||
});
|
||||
g_raw_mouse_handler->set_key_press_callback([this](const std::string& device_name, s32 scan_code, bool pressed)
|
||||
{
|
||||
key_press(device_name, scan_code, pressed);
|
||||
});
|
||||
|
||||
m_buttons = new QButtonGroup(this);
|
||||
connect(m_buttons, &QButtonGroup::idClicked, this, &raw_mouse_settings_dialog::on_button_click);
|
||||
|
@ -374,6 +378,32 @@ void raw_mouse_settings_dialog::mouse_press(const std::string& device_name, s32
|
|||
reactivate_buttons();
|
||||
}
|
||||
|
||||
void raw_mouse_settings_dialog::key_press(const std::string& device_name, s32 scan_code, bool pressed)
|
||||
{
|
||||
if (m_button_id < 0 || !pressed) // Let's only react to key presses
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const int player = m_tab_widget->currentIndex();
|
||||
const std::string current_device_name = get_current_device_name(player);
|
||||
|
||||
if (device_name != current_device_name)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
auto& config = ::at32(g_cfg_raw_mouse.players, player);
|
||||
config->get_button_by_index(m_button_id % button_count).from_string(fmt::format("%s%d", raw_mouse_config::key_prefix, scan_code));
|
||||
|
||||
if (auto button = m_buttons->button(m_button_id))
|
||||
{
|
||||
button->setText(QString::fromStdString(raw_mouse_config::get_key_name(scan_code)));
|
||||
}
|
||||
|
||||
reactivate_buttons();
|
||||
}
|
||||
|
||||
void raw_mouse_settings_dialog::handle_device_change(const std::string& device_name)
|
||||
{
|
||||
if (is_device_active(device_name))
|
||||
|
|
|
@ -31,6 +31,7 @@ private:
|
|||
void reset_config();
|
||||
void on_button_click(int id);
|
||||
void mouse_press(const std::string& device_name, s32 button_code, bool pressed);
|
||||
void key_press(const std::string& device_name, s32 scan_code, bool pressed);
|
||||
void handle_device_change(const std::string& device_name);
|
||||
bool is_device_active(const std::string& device_name);
|
||||
std::string get_current_device_name(int player);
|
||||
|
|
Loading…
Add table
Reference in a new issue