mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 19:45:20 +00:00
input: differentiate between left and right modifier keys
This commit is contained in:
parent
1cef7df006
commit
945bfaf0ea
4 changed files with 134 additions and 42 deletions
|
@ -94,7 +94,7 @@ void KeyboardHandlerBase::RemoveConsumer(keyboard_consumer::identifier id)
|
|||
}
|
||||
}
|
||||
|
||||
bool KeyboardHandlerBase::HandleKey(u32 code, bool pressed, bool is_auto_repeat, const std::u32string& key)
|
||||
bool KeyboardHandlerBase::HandleKey(u32 qt_code, u32 native_code, bool pressed, bool is_auto_repeat, const std::u32string& key)
|
||||
{
|
||||
bool consumed = false;
|
||||
|
||||
|
@ -102,13 +102,13 @@ bool KeyboardHandlerBase::HandleKey(u32 code, bool pressed, bool is_auto_repeat,
|
|||
|
||||
for (auto& [id, consumer] : m_consumers)
|
||||
{
|
||||
consumed |= consumer.ConsumeKey(code, pressed, is_auto_repeat, key);
|
||||
consumed |= consumer.ConsumeKey(qt_code, native_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 keyboard_consumer::ConsumeKey(u32 qt_code, u32 native_code, bool pressed, bool is_auto_repeat, const std::u32string& key)
|
||||
{
|
||||
bool consumed = false;
|
||||
|
||||
|
@ -124,22 +124,24 @@ bool keyboard_consumer::ConsumeKey(u32 code, bool pressed, bool is_auto_repeat,
|
|||
KbData& data = keyboard.m_data;
|
||||
const KbConfig& config = keyboard.m_config;
|
||||
|
||||
if (auto it = keyboard.m_keys.find(code); it != keyboard.m_keys.end())
|
||||
if (auto it = keyboard.m_keys.find(qt_code); it != keyboard.m_keys.end())
|
||||
{
|
||||
KbButton& button = it->second;
|
||||
|
||||
const u32 out_key_code = get_out_key_code(qt_code, native_code, button.m_outKeyCode);
|
||||
|
||||
u16 kcode = CELL_KEYC_NO_EVENT;
|
||||
bool is_meta_key = IsMetaKey(code);
|
||||
bool is_meta_key = IsMetaKey(qt_code);
|
||||
|
||||
if (!is_meta_key)
|
||||
{
|
||||
if (config.code_type == CELL_KB_CODETYPE_RAW)
|
||||
{
|
||||
kcode = button.m_outKeyCode;
|
||||
kcode = out_key_code;
|
||||
}
|
||||
else // config.code_type == CELL_KB_CODETYPE_ASCII
|
||||
{
|
||||
kcode = cellKbCnvRawCode(config.arrange, data.mkey, data.led, button.m_outKeyCode);
|
||||
kcode = cellKbCnvRawCode(config.arrange, data.mkey, data.led, out_key_code);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -153,33 +155,33 @@ bool keyboard_consumer::ConsumeKey(u32 code, bool pressed, bool is_auto_repeat,
|
|||
// Meta Keys
|
||||
if (is_meta_key)
|
||||
{
|
||||
data.mkey |= button.m_outKeyCode;
|
||||
data.mkey |= out_key_code;
|
||||
|
||||
if (config.read_mode == CELL_KB_RMODE_INPUTCHAR)
|
||||
{
|
||||
data.buttons[0] = KbButton(CELL_KEYC_NO_EVENT, button.m_outKeyCode, true);
|
||||
data.buttons[0] = KbButton(CELL_KEYC_NO_EVENT, out_key_code, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
data.buttons[data.len % CELL_KB_MAX_KEYCODES] = KbButton(CELL_KEYC_NO_EVENT, button.m_outKeyCode, true);
|
||||
data.buttons[data.len % CELL_KB_MAX_KEYCODES] = KbButton(CELL_KEYC_NO_EVENT, out_key_code, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Led Keys
|
||||
if (code == Key_CapsLock) data.led ^= CELL_KB_LED_CAPS_LOCK;
|
||||
if (code == Key_NumLock) data.led ^= CELL_KB_LED_NUM_LOCK;
|
||||
if (code == Key_ScrollLock) data.led ^= CELL_KB_LED_SCROLL_LOCK;
|
||||
// if (code == Key_Kana_Lock) data.led ^= CELL_KB_LED_KANA;
|
||||
// if (code == ???) data.led ^= CELL_KB_LED_COMPOSE;
|
||||
if (qt_code == Key_CapsLock) data.led ^= CELL_KB_LED_CAPS_LOCK;
|
||||
if (qt_code == Key_NumLock) data.led ^= CELL_KB_LED_NUM_LOCK;
|
||||
if (qt_code == Key_ScrollLock) data.led ^= CELL_KB_LED_SCROLL_LOCK;
|
||||
// if (qt_code == Key_Kana_Lock) data.led ^= CELL_KB_LED_KANA;
|
||||
// if (qt_code == ???) data.led ^= CELL_KB_LED_COMPOSE;
|
||||
|
||||
if (config.read_mode == CELL_KB_RMODE_INPUTCHAR)
|
||||
{
|
||||
data.buttons[0] = KbButton(kcode, button.m_outKeyCode, true);
|
||||
data.buttons[0] = KbButton(kcode, out_key_code, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
data.buttons[data.len % CELL_KB_MAX_KEYCODES] = KbButton(kcode, button.m_outKeyCode, true);
|
||||
data.buttons[data.len % CELL_KB_MAX_KEYCODES] = KbButton(kcode, out_key_code, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -190,13 +192,13 @@ bool keyboard_consumer::ConsumeKey(u32 code, bool pressed, bool is_auto_repeat,
|
|||
// Meta Keys
|
||||
if (is_meta_key)
|
||||
{
|
||||
data.mkey &= ~button.m_outKeyCode;
|
||||
data.mkey &= ~out_key_code;
|
||||
}
|
||||
|
||||
// Needed to indicate key releases. Without this you have to tap another key before using the same key again
|
||||
if (config.read_mode == CELL_KB_RMODE_INPUTCHAR)
|
||||
{
|
||||
data.buttons[0] = KbButton(CELL_KEYC_NO_EVENT, button.m_outKeyCode, false);
|
||||
data.buttons[0] = KbButton(CELL_KEYC_NO_EVENT, out_key_code, false);
|
||||
data.len = 1;
|
||||
}
|
||||
else
|
||||
|
@ -205,7 +207,7 @@ bool keyboard_consumer::ConsumeKey(u32 code, bool pressed, bool is_auto_repeat,
|
|||
|
||||
for (s32 i = 0; i < data.len; i++)
|
||||
{
|
||||
if (data.buttons[i].m_keyCode == kcode && (!is_meta_key || data.buttons[i].m_outKeyCode == button.m_outKeyCode))
|
||||
if (data.buttons[i].m_keyCode == kcode && (!is_meta_key || data.buttons[i].m_outKeyCode == out_key_code))
|
||||
{
|
||||
index = i;
|
||||
break;
|
||||
|
@ -219,7 +221,7 @@ bool keyboard_consumer::ConsumeKey(u32 code, bool pressed, bool is_auto_repeat,
|
|||
|
||||
if (data.len <= 1)
|
||||
{
|
||||
data.buttons[0] = KbButton(CELL_KEYC_NO_EVENT, button.m_outKeyCode, false);
|
||||
data.buttons[0] = KbButton(CELL_KEYC_NO_EVENT, out_key_code, false);
|
||||
}
|
||||
|
||||
data.len = std::max(1, data.len - 1);
|
||||
|
@ -247,10 +249,32 @@ bool keyboard_consumer::IsMetaKey(u32 code)
|
|||
return code == Key_Control
|
||||
|| code == Key_Shift
|
||||
|| code == Key_Alt
|
||||
|| code == Key_Meta
|
||||
|| code == Key_Super_L
|
||||
|| code == Key_Super_R;
|
||||
}
|
||||
|
||||
u32 keyboard_consumer::get_out_key_code(u32 qt_code, u32 native_code, u32 out_key_code)
|
||||
{
|
||||
// Parse native key codes to differentiate between left and right keys. (Qt sometimes really sucks)
|
||||
// NOTE: Qt throws a Ctrl key at us when using Alt Gr first, so right Alt does not work at the moment
|
||||
switch (qt_code)
|
||||
{
|
||||
case Key_Control:
|
||||
return native_code == native_key::ctrl_l ? CELL_KB_MKEY_L_CTRL : CELL_KB_MKEY_R_CTRL;
|
||||
case Key_Shift:
|
||||
return native_code == native_key::shift_l ? CELL_KB_MKEY_L_SHIFT : CELL_KB_MKEY_R_SHIFT;
|
||||
case Key_Alt:
|
||||
return native_code == native_key::alt_l ? CELL_KB_MKEY_L_ALT : CELL_KB_MKEY_R_ALT;
|
||||
case Key_Meta:
|
||||
return native_code == native_key::meta_l ? CELL_KB_MKEY_L_WIN : CELL_KB_MKEY_R_WIN;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return out_key_code;
|
||||
}
|
||||
|
||||
void KeyboardHandlerBase::SetIntercepted(bool intercepted)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
|
@ -294,12 +318,33 @@ void keyboard_consumer::ReleaseAllKeys()
|
|||
{
|
||||
for (const auto& [key_code, button] : keyboard.m_keys)
|
||||
{
|
||||
ConsumeKey(button.m_keyCode, false, false, {});
|
||||
switch (button.m_keyCode)
|
||||
{
|
||||
case Key_Control:
|
||||
ConsumeKey(button.m_keyCode, native_key::ctrl_l, false, false, {});
|
||||
ConsumeKey(button.m_keyCode, native_key::ctrl_r, false, false, {});
|
||||
break;
|
||||
case Key_Shift:
|
||||
ConsumeKey(button.m_keyCode, native_key::shift_l, false, false, {});
|
||||
ConsumeKey(button.m_keyCode, native_key::shift_r, false, false, {});
|
||||
break;
|
||||
case Key_Alt:
|
||||
ConsumeKey(button.m_keyCode, native_key::alt_l, false, false, {});
|
||||
ConsumeKey(button.m_keyCode, native_key::alt_r, false, false, {});
|
||||
break;
|
||||
case Key_Meta:
|
||||
ConsumeKey(button.m_keyCode, native_key::meta_l, false, false, {});
|
||||
ConsumeKey(button.m_keyCode, native_key::meta_r, false, false, {});
|
||||
break;
|
||||
default:
|
||||
ConsumeKey(button.m_keyCode, 0, false, false, {});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (const std::u32string& key : keyboard.m_extra_data.pressed_keys)
|
||||
{
|
||||
ConsumeKey(CELL_KEYC_NO_EVENT, false, false, key);
|
||||
ConsumeKey(CELL_KEYC_NO_EVENT, 0, false, false, key);
|
||||
}
|
||||
|
||||
keyboard.m_extra_data.pressed_keys.clear();
|
||||
|
|
|
@ -22,6 +22,39 @@ enum QtKeys
|
|||
Key_Super_R = 0x01000054
|
||||
};
|
||||
|
||||
// See https://developer.mozilla.org/en-US/docs/Web/API/UI_Events/Keyboard_event_code_values
|
||||
enum native_key : u32
|
||||
{
|
||||
#ifdef _WIN32
|
||||
ctrl_l = 0x001D,
|
||||
ctrl_r = 0xE01D,
|
||||
shift_l = 0x002A,
|
||||
shift_r = 0x0036,
|
||||
alt_l = 0x0038,
|
||||
alt_r = 0xE038,
|
||||
meta_l = 0xE05B,
|
||||
meta_r = 0xE05C,
|
||||
#elif defined (__APPLE__)
|
||||
ctrl_l = 0x3B, // kVK_Control
|
||||
ctrl_r = 0x3E, // kVK_RightControl
|
||||
shift_l = 0x38, // kVK_Shift
|
||||
shift_r = 0x3C, // kVK_RightShift
|
||||
alt_l = 0x3A, // kVK_Option
|
||||
alt_r = 0x3D, // kVK_RightOption
|
||||
meta_l = 0x37, // kVK_Command
|
||||
meta_r = 0x36, // kVK_RightCommand
|
||||
#else
|
||||
ctrl_l = 0x0025,
|
||||
ctrl_r = 0x0069,
|
||||
shift_l = 0x0032,
|
||||
shift_r = 0x003E,
|
||||
alt_l = 0x0040,
|
||||
alt_r = 0x006C,
|
||||
meta_l = 0x0085,
|
||||
meta_r = 0x0086,
|
||||
#endif
|
||||
};
|
||||
|
||||
struct KbInfo
|
||||
{
|
||||
u32 max_connect = 0;
|
||||
|
@ -88,7 +121,7 @@ public:
|
|||
keyboard_consumer() {}
|
||||
keyboard_consumer(identifier id) : m_id(id) {}
|
||||
|
||||
bool ConsumeKey(u32 code, bool pressed, bool is_auto_repeat, const std::u32string& key);
|
||||
bool ConsumeKey(u32 qt_code, u32 native_code, bool pressed, bool is_auto_repeat, const std::u32string& key);
|
||||
void SetIntercepted(bool intercepted);
|
||||
|
||||
static bool IsMetaKey(u32 code);
|
||||
|
@ -103,6 +136,8 @@ public:
|
|||
void ReleaseAllKeys();
|
||||
|
||||
protected:
|
||||
u32 get_out_key_code(u32 qt_code, u32 native_code, u32 out_key_code);
|
||||
|
||||
identifier m_id = identifier::unknown;
|
||||
KbInfo m_info{};
|
||||
std::vector<Keyboard> m_keyboards;
|
||||
|
@ -126,7 +161,7 @@ public:
|
|||
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);
|
||||
bool HandleKey(u32 qt_code, u32 native_code, bool pressed, bool is_auto_repeat, const std::u32string& key);
|
||||
void SetIntercepted(bool intercepted);
|
||||
|
||||
stx::init_mutex init;
|
||||
|
|
|
@ -110,7 +110,7 @@ void basic_keyboard_handler::keyPressEvent(QKeyEvent* keyEvent)
|
|||
|
||||
const int key = getUnmodifiedKey(keyEvent);
|
||||
|
||||
if (key < 0 || !HandleKey(static_cast<u32>(key), true, keyEvent->isAutoRepeat(), keyEvent->text().toStdU32String()))
|
||||
if (key < 0 || !HandleKey(static_cast<u32>(key), keyEvent->nativeScanCode(), true, keyEvent->isAutoRepeat(), keyEvent->text().toStdU32String()))
|
||||
{
|
||||
keyEvent->ignore();
|
||||
}
|
||||
|
@ -131,7 +131,7 @@ void basic_keyboard_handler::keyReleaseEvent(QKeyEvent* keyEvent)
|
|||
|
||||
const int key = getUnmodifiedKey(keyEvent);
|
||||
|
||||
if (key < 0 || !HandleKey(static_cast<u32>(key), false, keyEvent->isAutoRepeat(), keyEvent->text().toStdU32String()))
|
||||
if (key < 0 || !HandleKey(static_cast<u32>(key), keyEvent->nativeScanCode(), false, keyEvent->isAutoRepeat(), keyEvent->text().toStdU32String()))
|
||||
{
|
||||
keyEvent->ignore();
|
||||
}
|
||||
|
@ -182,11 +182,14 @@ void basic_keyboard_handler::LoadSettings(Keyboard& keyboard)
|
|||
buttons.emplace_back(Qt::Key_Control, CELL_KB_MKEY_L_CTRL);
|
||||
buttons.emplace_back(Qt::Key_Shift, CELL_KB_MKEY_L_SHIFT);
|
||||
buttons.emplace_back(Qt::Key_Alt, CELL_KB_MKEY_L_ALT);
|
||||
buttons.emplace_back(Qt::Key_Super_L, CELL_KB_MKEY_L_WIN);
|
||||
buttons.emplace_back(Qt::Key_Meta, CELL_KB_MKEY_L_WIN);
|
||||
//buttons.emplace_back(, CELL_KB_MKEY_R_CTRL); // There is no way to know if it's left or right in Qt at the moment
|
||||
//buttons.emplace_back(, CELL_KB_MKEY_R_SHIFT); // There is no way to know if it's left or right in Qt at the moment
|
||||
//buttons.emplace_back(, CELL_KB_MKEY_R_ALT); // There is no way to know if it's left or right in Qt at the moment
|
||||
buttons.emplace_back(Qt::Key_Super_R, CELL_KB_MKEY_R_WIN);
|
||||
//buttons.emplace_back(, CELL_KB_MKEY_R_WIN); // There is no way to know if it's left or right in Qt at the moment
|
||||
|
||||
buttons.emplace_back(Qt::Key_Super_L, CELL_KB_MKEY_L_WIN); // The super keys are supposed to be the windows keys, but they trigger the meta key instead. Let's assign the windows keys to both.
|
||||
buttons.emplace_back(Qt::Key_Super_R, CELL_KB_MKEY_R_WIN); // The super keys are supposed to be the windows keys, but they trigger the meta key instead. Let's assign the windows keys to both.
|
||||
|
||||
// CELL_KB_RAWDAT
|
||||
//buttons.emplace_back(, CELL_KEYC_NO_EVENT); // Redundant, listed for completeness
|
||||
|
@ -222,7 +225,7 @@ void basic_keyboard_handler::LoadSettings(Keyboard& keyboard)
|
|||
buttons.emplace_back(Qt::Key_Down, CELL_KEYC_DOWN_ARROW);
|
||||
buttons.emplace_back(Qt::Key_Up, CELL_KEYC_UP_ARROW);
|
||||
//buttons.emplace_back(, CELL_KEYC_NUM_LOCK);
|
||||
buttons.emplace_back(Qt::Key_Meta, CELL_KEYC_APPLICATION);
|
||||
//buttons.emplace_back(, CELL_KEYC_APPLICATION); // This is probably the PS key on the PS3 keyboard
|
||||
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_Muhenkan, CELL_KEYC_MUHENKAN);
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
#include "keyboard_pad_handler.h"
|
||||
#include "pad_thread.h"
|
||||
#include "Emu/Io/pad_config.h"
|
||||
#include "Emu/Io/KeyboardHandler.h"
|
||||
#include "Input/product_info.h"
|
||||
#include "rpcs3qt/gs_frame.h"
|
||||
|
||||
|
@ -821,12 +822,16 @@ u32 keyboard_pad_handler::GetKeyCode(const QString& keyName)
|
|||
|
||||
int keyboard_pad_handler::native_scan_code_from_string([[maybe_unused]] const std::string& key)
|
||||
{
|
||||
// NOTE: Qt throws a Ctrl key at us when using Alt Gr, so there is no point in distinguishing left and right Alt at the moment
|
||||
// NOTE: Qt throws a Ctrl key at us when using Alt Gr first, so right Alt does not work at the moment
|
||||
if (key == "Shift Left") return native_key::shift_l;
|
||||
if (key == "Shift Right") return native_key::shift_r;
|
||||
if (key == "Ctrl Left") return native_key::ctrl_l;
|
||||
if (key == "Ctrl Right") return native_key::ctrl_r;
|
||||
if (key == "Alt Left") return native_key::alt_l;
|
||||
if (key == "Alt Right") return native_key::alt_r;
|
||||
if (key == "Meta Left") return native_key::meta_l;
|
||||
if (key == "Meta Right") return native_key::meta_r;
|
||||
#ifdef _WIN32
|
||||
if (key == "Shift Left") return 42;
|
||||
if (key == "Shift Right") return 54;
|
||||
if (key == "Ctrl Left") return 29;
|
||||
if (key == "Ctrl Right") return 285;
|
||||
if (key == "Num+0" || key == "Num+Ins") return 82;
|
||||
if (key == "Num+1" || key == "Num+End") return 79;
|
||||
if (key == "Num+2" || key == "Num+Down") return 80;
|
||||
|
@ -851,15 +856,20 @@ int keyboard_pad_handler::native_scan_code_from_string([[maybe_unused]] const st
|
|||
|
||||
std::string keyboard_pad_handler::native_scan_code_to_string(int native_scan_code)
|
||||
{
|
||||
// NOTE: the other Qt function "nativeVirtualKey" does not distinguish between VK_SHIFT and VK_RSHIFT key in Qt at the moment
|
||||
// NOTE: Qt throws a Ctrl key at us when using Alt Gr first, so right Alt does not work at the moment
|
||||
// NOTE: for MacOs: nativeScanCode may not work
|
||||
switch (native_scan_code)
|
||||
{
|
||||
case native_key::shift_l: return "Shift Left";
|
||||
case native_key::shift_r: return "Shift Right";
|
||||
case native_key::ctrl_l: return "Ctrl Left";
|
||||
case native_key::ctrl_r: return "Ctrl Right";
|
||||
case native_key::alt_l: return "Alt Left";
|
||||
case native_key::alt_r: return "Alt Right";
|
||||
case native_key::meta_l: return "Meta Left";
|
||||
case native_key::meta_r: return "Meta Right";
|
||||
#ifdef _WIN32
|
||||
// NOTE: the other Qt function "nativeVirtualKey" does not distinguish between VK_SHIFT and VK_RSHIFT key in Qt at the moment
|
||||
// NOTE: Qt throws a Ctrl key at us when using Alt Gr, so there is no point in distinguishing left and right Alt at the moment
|
||||
case 42: return "Shift Left";
|
||||
case 54: return "Shift Right";
|
||||
case 29: return "Ctrl Left";
|
||||
case 285: return "Ctrl Right";
|
||||
case 82: return "Num+0"; // Also "Num+Ins" depending on numlock
|
||||
case 79: return "Num+1"; // Also "Num+End" depending on numlock
|
||||
case 80: return "Num+2"; // Also "Num+Down" depending on numlock
|
||||
|
@ -878,7 +888,6 @@ std::string keyboard_pad_handler::native_scan_code_to_string(int native_scan_cod
|
|||
case 284: return "Num+Enter";
|
||||
#else
|
||||
// TODO
|
||||
// NOTE for MacOs: nativeScanCode may not work
|
||||
#endif
|
||||
default: return "";
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue