mirror of
				https://github.com/godotengine/godot.git
				synced 2025-10-31 13:41:03 +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; | ||||
| } | ||||
| 
 | ||||
| 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.
 | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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) { | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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.
 | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue
	
	 Riteo
						Riteo