diff --git a/platform/linuxbsd/wayland/key_mapping_xkb.cpp b/platform/linuxbsd/wayland/key_mapping_xkb.cpp index bd1a1e383515..7d3a4272f5ad 100644 --- a/platform/linuxbsd/wayland/key_mapping_xkb.cpp +++ b/platform/linuxbsd/wayland/key_mapping_xkb.cpp @@ -369,6 +369,30 @@ void KeyMappingXKB::initialize() { 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) { if (p_keysym >= 0x20 && p_keysym < 0x7E) { // ASCII, maps 1-1 if (p_keysym > 0x60 && p_keysym < 0x7B) { // Lowercase ASCII. diff --git a/platform/linuxbsd/wayland/key_mapping_xkb.h b/platform/linuxbsd/wayland/key_mapping_xkb.h index 9b8c90a445e0..508bb0287866 100644 --- a/platform/linuxbsd/wayland/key_mapping_xkb.h +++ b/platform/linuxbsd/wayland/key_mapping_xkb.h @@ -56,6 +56,7 @@ class KeyMappingXKB { public: static void initialize(); + static bool is_sym_numpad(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 Key get_scancode(unsigned int p_code); diff --git a/platform/linuxbsd/wayland/wayland_thread.cpp b/platform/linuxbsd/wayland/wayland_thread.cpp index f048a3f294d6..6155d9e3675d 100644 --- a/platform/linuxbsd/wayland/wayland_thread.cpp +++ b/platform/linuxbsd/wayland/wayland_thread.cpp @@ -193,18 +193,26 @@ Vector WaylandThread::_wp_primary_selection_offer_read(struct wl_displa // Sets up an `InputEventKey` and returns whether it has any meaningful value. bool WaylandThread::_seat_state_configure_key_event(SeatState &p_ss, Ref p_event, xkb_keycode_t p_keycode, bool p_pressed) { - // 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); + xkb_keysym_t shifted_sym = xkb_state_key_get_one_sym(p_ss.xkb_state, p_keycode); Key physical_keycode = KeyMappingXKB::get_scancode(p_keycode); KeyLocation key_location = KeyMappingXKB::get_location(p_keycode); uint32_t unicode = xkb_state_key_get_utf32(p_ss.xkb_state, p_keycode); 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) { diff --git a/platform/linuxbsd/x11/display_server_x11.cpp b/platform/linuxbsd/x11/display_server_x11.cpp index cbd3662986c7..18500f701963 100644 --- a/platform/linuxbsd/x11/display_server_x11.cpp +++ b/platform/linuxbsd/x11/display_server_x11.cpp @@ -3562,8 +3562,7 @@ void DisplayServerX11::_handle_key_event(WindowID p_window, XKeyEvent *p_event, // XLookupString returns keysyms usable as nice keycodes. char str[256] = {}; XKeyEvent xkeyevent_no_mod = *xkeyevent; - xkeyevent_no_mod.state &= ~ShiftMask; - xkeyevent_no_mod.state &= ~ControlMask; + xkeyevent_no_mod.state &= 0xFF00; XLookupString(xkeyevent, str, 255, &keysym_unicode, 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) { 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); 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 (xkb_compose_state_get_status(wd.xkb_state) == XKB_COMPOSE_COMPOSED) { bool keypress = xkeyevent->type == KeyPress; - Key keycode = KeyMappingX11::get_keycode(keysym_keycode); Key physical_keycode = KeyMappingX11::get_scancode(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) { 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 // 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); KeyLocation key_location = KeyMappingX11::get_location(xkeyevent->keycode); diff --git a/platform/linuxbsd/x11/key_mapping_x11.cpp b/platform/linuxbsd/x11/key_mapping_x11.cpp index b589a2a57344..e6494985a4a2 100644 --- a/platform/linuxbsd/x11/key_mapping_x11.cpp +++ b/platform/linuxbsd/x11/key_mapping_x11.cpp @@ -1129,6 +1129,30 @@ void KeyMappingX11::initialize() { 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) { if (p_keysym >= 0x20 && p_keysym < 0x7E) { // ASCII, maps 1-1 if (p_keysym > 0x60 && p_keysym < 0x7B) { // Lowercase ASCII. diff --git a/platform/linuxbsd/x11/key_mapping_x11.h b/platform/linuxbsd/x11/key_mapping_x11.h index a51ee5f48eab..27cd8af7cf58 100644 --- a/platform/linuxbsd/x11/key_mapping_x11.h +++ b/platform/linuxbsd/x11/key_mapping_x11.h @@ -61,6 +61,7 @@ class KeyMappingX11 { public: static void initialize(); + static bool is_sym_numpad(KeySym p_keysym); static Key get_keycode(KeySym p_keysym); static unsigned int get_xlibcode(Key p_keysym); static Key get_scancode(unsigned int p_code);