mirror of
https://github.com/godotengine/godot.git
synced 2025-10-24 02:13:36 +00:00
Linux/BSD: Modify only keypad keys
The `keycode` field of `InputEventKey` is supposed to be "unshifted"; That is, what the key would output if no modifier keys were pressed. This should match what's written on the key label, but `Key` enumerates also all keypad keys, which require a modifier. We thus require some extra checks for them. Note that this can still allow "stuck keys", but that's an even deeper problem.
This commit is contained in:
parent
a013481b09
commit
140a63be25
6 changed files with 96 additions and 11 deletions
|
|
@ -369,6 +369,30 @@ void KeyMappingXKB::initialize() {
|
||||||
location_map[0x86] = KeyLocation::RIGHT;
|
location_map[0x86] = KeyLocation::RIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool KeyMappingXKB::is_sym_numpad(xkb_keysym_t p_keysym) {
|
||||||
|
switch (p_keysym) {
|
||||||
|
case XKB_KEY_KP_Multiply:
|
||||||
|
case XKB_KEY_KP_Divide:
|
||||||
|
case XKB_KEY_KP_Subtract:
|
||||||
|
case XKB_KEY_KP_Separator:
|
||||||
|
case XKB_KEY_KP_Add:
|
||||||
|
case XKB_KEY_KP_0:
|
||||||
|
case XKB_KEY_KP_1:
|
||||||
|
case XKB_KEY_KP_2:
|
||||||
|
case XKB_KEY_KP_3:
|
||||||
|
case XKB_KEY_KP_4:
|
||||||
|
case XKB_KEY_KP_5:
|
||||||
|
case XKB_KEY_KP_6:
|
||||||
|
case XKB_KEY_KP_7:
|
||||||
|
case XKB_KEY_KP_8:
|
||||||
|
case XKB_KEY_KP_9: {
|
||||||
|
return true;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Key KeyMappingXKB::get_keycode(xkb_keycode_t p_keysym) {
|
Key KeyMappingXKB::get_keycode(xkb_keycode_t p_keysym) {
|
||||||
if (p_keysym >= 0x20 && p_keysym < 0x7E) { // ASCII, maps 1-1
|
if (p_keysym >= 0x20 && p_keysym < 0x7E) { // ASCII, maps 1-1
|
||||||
if (p_keysym > 0x60 && p_keysym < 0x7B) { // Lowercase ASCII.
|
if (p_keysym > 0x60 && p_keysym < 0x7B) { // Lowercase ASCII.
|
||||||
|
|
|
||||||
|
|
@ -56,6 +56,7 @@ class KeyMappingXKB {
|
||||||
public:
|
public:
|
||||||
static void initialize();
|
static void initialize();
|
||||||
|
|
||||||
|
static bool is_sym_numpad(xkb_keysym_t p_keysym);
|
||||||
static Key get_keycode(xkb_keysym_t p_keysym);
|
static Key get_keycode(xkb_keysym_t p_keysym);
|
||||||
static xkb_keycode_t get_xkb_keycode(Key p_keycode);
|
static xkb_keycode_t get_xkb_keycode(Key p_keycode);
|
||||||
static Key get_scancode(unsigned int p_code);
|
static Key get_scancode(unsigned int p_code);
|
||||||
|
|
|
||||||
|
|
@ -193,18 +193,26 @@ Vector<uint8_t> WaylandThread::_wp_primary_selection_offer_read(struct wl_displa
|
||||||
|
|
||||||
// Sets up an `InputEventKey` and returns whether it has any meaningful value.
|
// Sets up an `InputEventKey` and returns whether it has any meaningful value.
|
||||||
bool WaylandThread::_seat_state_configure_key_event(SeatState &p_ss, Ref<InputEventKey> p_event, xkb_keycode_t p_keycode, bool p_pressed) {
|
bool WaylandThread::_seat_state_configure_key_event(SeatState &p_ss, Ref<InputEventKey> p_event, xkb_keycode_t p_keycode, bool p_pressed) {
|
||||||
// NOTE: xkbcommon's API really encourages to apply the modifier state but we
|
xkb_keysym_t shifted_sym = xkb_state_key_get_one_sym(p_ss.xkb_state, p_keycode);
|
||||||
// only want a "plain" symbol so that we can convert it into a godot keycode.
|
|
||||||
const xkb_keysym_t *syms = nullptr;
|
|
||||||
int num_sys = xkb_keymap_key_get_syms_by_level(p_ss.xkb_keymap, p_keycode, p_ss.current_layout_index, 0, &syms);
|
|
||||||
|
|
||||||
Key physical_keycode = KeyMappingXKB::get_scancode(p_keycode);
|
Key physical_keycode = KeyMappingXKB::get_scancode(p_keycode);
|
||||||
KeyLocation key_location = KeyMappingXKB::get_location(p_keycode);
|
KeyLocation key_location = KeyMappingXKB::get_location(p_keycode);
|
||||||
uint32_t unicode = xkb_state_key_get_utf32(p_ss.xkb_state, p_keycode);
|
uint32_t unicode = xkb_state_key_get_utf32(p_ss.xkb_state, p_keycode);
|
||||||
|
|
||||||
Key keycode = Key::NONE;
|
Key keycode = Key::NONE;
|
||||||
if (num_sys > 0 && syms) {
|
|
||||||
keycode = KeyMappingXKB::get_keycode(syms[0]);
|
if (KeyMappingXKB::is_sym_numpad(shifted_sym)) {
|
||||||
|
keycode = KeyMappingXKB::get_keycode(shifted_sym);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keycode == Key::NONE) {
|
||||||
|
// NOTE: xkbcommon's API really encourages to apply the modifier state but we
|
||||||
|
// only want a "plain" symbol so that we can convert it into a godot keycode.
|
||||||
|
const xkb_keysym_t *syms = nullptr;
|
||||||
|
int num_sys = xkb_keymap_key_get_syms_by_level(p_ss.xkb_keymap, p_keycode, p_ss.current_layout_index, 0, &syms);
|
||||||
|
if (num_sys > 0 && syms) {
|
||||||
|
keycode = KeyMappingXKB::get_keycode(syms[0]);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keycode == Key::NONE) {
|
if (keycode == Key::NONE) {
|
||||||
|
|
|
||||||
|
|
@ -3562,8 +3562,7 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
|
||||||
// XLookupString returns keysyms usable as nice keycodes.
|
// XLookupString returns keysyms usable as nice keycodes.
|
||||||
char str[256] = {};
|
char str[256] = {};
|
||||||
XKeyEvent xkeyevent_no_mod = *xkeyevent;
|
XKeyEvent xkeyevent_no_mod = *xkeyevent;
|
||||||
xkeyevent_no_mod.state &= ~ShiftMask;
|
xkeyevent_no_mod.state &= 0xFF00;
|
||||||
xkeyevent_no_mod.state &= ~ControlMask;
|
|
||||||
XLookupString(xkeyevent, str, 255, &keysym_unicode, nullptr);
|
XLookupString(xkeyevent, str, 255, &keysym_unicode, nullptr);
|
||||||
XLookupString(&xkeyevent_no_mod, nullptr, 0, &keysym_keycode, nullptr);
|
XLookupString(&xkeyevent_no_mod, nullptr, 0, &keysym_keycode, nullptr);
|
||||||
|
|
||||||
|
|
@ -3601,7 +3600,17 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
|
||||||
|
|
||||||
if (status == XLookupChars) {
|
if (status == XLookupChars) {
|
||||||
bool keypress = xkeyevent->type == KeyPress;
|
bool keypress = xkeyevent->type == KeyPress;
|
||||||
Key keycode = KeyMappingX11::get_keycode(keysym_keycode);
|
|
||||||
|
Key keycode = Key::NONE;
|
||||||
|
if (KeyMappingX11::is_sym_numpad(keysym_unicode)) {
|
||||||
|
// Special case for numpad keys.
|
||||||
|
keycode = KeyMappingX11::get_keycode(keysym_unicode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keycode == Key::NONE) {
|
||||||
|
keycode = KeyMappingX11::get_keycode(keysym_keycode);
|
||||||
|
}
|
||||||
|
|
||||||
Key physical_keycode = KeyMappingX11::get_scancode(xkeyevent->keycode);
|
Key physical_keycode = KeyMappingX11::get_scancode(xkeyevent->keycode);
|
||||||
|
|
||||||
if (keycode >= Key::A + 32 && keycode <= Key::Z + 32) {
|
if (keycode >= Key::A + 32 && keycode <= Key::Z + 32) {
|
||||||
|
|
@ -3669,10 +3678,19 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
|
||||||
if (res == XKB_COMPOSE_FEED_ACCEPTED) {
|
if (res == XKB_COMPOSE_FEED_ACCEPTED) {
|
||||||
if (xkb_compose_state_get_status(wd.xkb_state) == XKB_COMPOSE_COMPOSED) {
|
if (xkb_compose_state_get_status(wd.xkb_state) == XKB_COMPOSE_COMPOSED) {
|
||||||
bool keypress = xkeyevent->type == KeyPress;
|
bool keypress = xkeyevent->type == KeyPress;
|
||||||
Key keycode = KeyMappingX11::get_keycode(keysym_keycode);
|
|
||||||
Key physical_keycode = KeyMappingX11::get_scancode(xkeyevent->keycode);
|
Key physical_keycode = KeyMappingX11::get_scancode(xkeyevent->keycode);
|
||||||
KeyLocation key_location = KeyMappingX11::get_location(xkeyevent->keycode);
|
KeyLocation key_location = KeyMappingX11::get_location(xkeyevent->keycode);
|
||||||
|
|
||||||
|
Key keycode = Key::NONE;
|
||||||
|
if (KeyMappingX11::is_sym_numpad(keysym_unicode)) {
|
||||||
|
// Special case for numpad keys.
|
||||||
|
keycode = KeyMappingX11::get_keycode(keysym_unicode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keycode == Key::NONE) {
|
||||||
|
keycode = KeyMappingX11::get_keycode(keysym_keycode);
|
||||||
|
}
|
||||||
|
|
||||||
if (keycode >= Key::A + 32 && keycode <= Key::Z + 32) {
|
if (keycode >= Key::A + 32 && keycode <= Key::Z + 32) {
|
||||||
keycode -= 'a' - 'A';
|
keycode -= 'a' - 'A';
|
||||||
}
|
}
|
||||||
|
|
@ -3733,7 +3751,16 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event,
|
||||||
// KeyMappingX11 just translated the X11 keysym to a PIGUI
|
// KeyMappingX11 just translated the X11 keysym to a PIGUI
|
||||||
// keysym, so it works in all platforms the same.
|
// keysym, so it works in all platforms the same.
|
||||||
|
|
||||||
Key keycode = KeyMappingX11::get_keycode(keysym_keycode);
|
Key keycode = Key::NONE;
|
||||||
|
if (KeyMappingX11::is_sym_numpad(keysym_unicode)) {
|
||||||
|
// Special case for numpad keys.
|
||||||
|
keycode = KeyMappingX11::get_keycode(keysym_unicode);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (keycode == Key::NONE) {
|
||||||
|
keycode = KeyMappingX11::get_keycode(keysym_keycode);
|
||||||
|
}
|
||||||
|
|
||||||
Key physical_keycode = KeyMappingX11::get_scancode(xkeyevent->keycode);
|
Key physical_keycode = KeyMappingX11::get_scancode(xkeyevent->keycode);
|
||||||
|
|
||||||
KeyLocation key_location = KeyMappingX11::get_location(xkeyevent->keycode);
|
KeyLocation key_location = KeyMappingX11::get_location(xkeyevent->keycode);
|
||||||
|
|
|
||||||
|
|
@ -1129,6 +1129,30 @@ void KeyMappingX11::initialize() {
|
||||||
location_map[0x86] = KeyLocation::RIGHT;
|
location_map[0x86] = KeyLocation::RIGHT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool KeyMappingX11::is_sym_numpad(KeySym p_keysym) {
|
||||||
|
switch (p_keysym) {
|
||||||
|
case XK_KP_Multiply:
|
||||||
|
case XK_KP_Divide:
|
||||||
|
case XK_KP_Subtract:
|
||||||
|
case XK_KP_Separator:
|
||||||
|
case XK_KP_Add:
|
||||||
|
case XK_KP_0:
|
||||||
|
case XK_KP_1:
|
||||||
|
case XK_KP_2:
|
||||||
|
case XK_KP_3:
|
||||||
|
case XK_KP_4:
|
||||||
|
case XK_KP_5:
|
||||||
|
case XK_KP_6:
|
||||||
|
case XK_KP_7:
|
||||||
|
case XK_KP_8:
|
||||||
|
case XK_KP_9: {
|
||||||
|
return true;
|
||||||
|
} break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Key KeyMappingX11::get_keycode(KeySym p_keysym) {
|
Key KeyMappingX11::get_keycode(KeySym p_keysym) {
|
||||||
if (p_keysym >= 0x20 && p_keysym < 0x7E) { // ASCII, maps 1-1
|
if (p_keysym >= 0x20 && p_keysym < 0x7E) { // ASCII, maps 1-1
|
||||||
if (p_keysym > 0x60 && p_keysym < 0x7B) { // Lowercase ASCII.
|
if (p_keysym > 0x60 && p_keysym < 0x7B) { // Lowercase ASCII.
|
||||||
|
|
|
||||||
|
|
@ -61,6 +61,7 @@ class KeyMappingX11 {
|
||||||
public:
|
public:
|
||||||
static void initialize();
|
static void initialize();
|
||||||
|
|
||||||
|
static bool is_sym_numpad(KeySym p_keysym);
|
||||||
static Key get_keycode(KeySym p_keysym);
|
static Key get_keycode(KeySym p_keysym);
|
||||||
static unsigned int get_xlibcode(Key p_keysym);
|
static unsigned int get_xlibcode(Key p_keysym);
|
||||||
static Key get_scancode(unsigned int p_code);
|
static Key get_scancode(unsigned int p_code);
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue