1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-07 12:30:27 +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:
Riteo
2025-01-29 20:24:46 +01:00
parent a013481b09
commit 140a63be25
6 changed files with 96 additions and 11 deletions

View File

@@ -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.

View File

@@ -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);

View File

@@ -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.
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
// 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) {