improvements to hardware keyboard handling

This commit is contained in:
Helium314 2025-06-14 12:53:46 +02:00
parent 9c97a6b9bf
commit e430d13c4a
2 changed files with 22 additions and 5 deletions

View file

@ -10,6 +10,8 @@ import android.view.KeyCharacterMap
import android.view.KeyEvent import android.view.KeyEvent
import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode import helium314.keyboard.keyboard.internal.keyboard_parser.floris.KeyCode
import helium314.keyboard.latin.common.Constants import helium314.keyboard.latin.common.Constants
import helium314.keyboard.latin.utils.Log
import helium314.keyboard.latin.utils.getCustomKeyCode
/** /**
* A hardware event decoder for a hardware qwerty-ish keyboard. * A hardware event decoder for a hardware qwerty-ish keyboard.
@ -24,7 +26,8 @@ class HardwareKeyboardEventDecoder(val mDeviceId: Int) : HardwareEventDecoder {
// KeyEvent#getUnicodeChar() does not exactly returns a unicode char, but rather a value // KeyEvent#getUnicodeChar() does not exactly returns a unicode char, but rather a value
// that includes both the unicode char in the lower 21 bits and flags in the upper bits, // that includes both the unicode char in the lower 21 bits and flags in the upper bits,
// hence the name "codePointAndFlags". {@see KeyEvent#getUnicodeChar()} for more info. // hence the name "codePointAndFlags". {@see KeyEvent#getUnicodeChar()} for more info.
val codePointAndFlags = keyEvent.unicodeChar val codePointAndFlags = keyEvent.unicodeChar.takeIf { it != 0 }
?: Event.NOT_A_CODE_POINT // KeyEvent has 0 if no codePoint, but that's actually valid so we convert it to -1
// The keyCode is the abstraction used by the KeyEvent to represent different keys that // The keyCode is the abstraction used by the KeyEvent to represent different keys that
// do not necessarily map to a unicode character. This represents a physical key, like // do not necessarily map to a unicode character. This represents a physical key, like
// the key for 'A' or Space, but also Backspace or Ctrl or Caps Lock. // the key for 'A' or Space, but also Backspace or Ctrl or Caps Lock.
@ -48,8 +51,21 @@ class HardwareKeyboardEventDecoder(val mDeviceId: Int) : HardwareEventDecoder {
} else Event.createHardwareKeypressEvent(codePointAndFlags, keyCode, metaState, null, isKeyRepeat) } else Event.createHardwareKeypressEvent(codePointAndFlags, keyCode, metaState, null, isKeyRepeat)
// If not Enter, then this is just a regular keypress event for a normal character // If not Enter, then this is just a regular keypress event for a normal character
// that can be committed right away, taking into account the current state. // that can be committed right away, taking into account the current state.
} else if (isDpadDirection(keyCode)) {
Event.createHardwareKeypressEvent(codePointAndFlags, keyCode, metaState, null, isKeyRepeat)
// } else if (KeyEvent.isModifierKey(keyCode)) {
// todo: we could synchronize meta state across HW and SW keyboard, but that's more work for little benefit (especially with shift & caps lock)
} else { } else {
Event.notHandledEvent Event.notHandledEvent
} }
} }
companion object {
private fun isDpadDirection(keyCode: Int) = when (keyCode) {
KeyEvent.KEYCODE_DPAD_UP, KeyEvent.KEYCODE_DPAD_DOWN, KeyEvent.KEYCODE_DPAD_LEFT, KeyEvent.KEYCODE_DPAD_RIGHT,
KeyEvent.KEYCODE_DPAD_DOWN_LEFT, KeyEvent.KEYCODE_DPAD_DOWN_RIGHT, KeyEvent.KEYCODE_DPAD_UP_RIGHT,
KeyEvent.KEYCODE_DPAD_UP_LEFT -> true
else -> false
}
}
} }

View file

@ -780,15 +780,16 @@ public final class InputLogic {
default: default:
if (KeyCode.INSTANCE.isModifier(keyCode)) if (KeyCode.INSTANCE.isModifier(keyCode))
return; // continuation of previous switch case above, but modifiers are held in a separate place return; // continuation of previous switch case above, but modifiers are held in a separate place
final int keyEventCode = event.getMCodePoint() <= 0 final int keyEventCode = keyCode > 0
? KeyCode.keyCodeToKeyEventCode(keyCode) ? keyCode
: KeyCode.codePointToKeyEventCode(event.getMCodePoint()); : event.getMCodePoint() >= 0 ? KeyCode.codePointToKeyEventCode(event.getMCodePoint())
: KeyCode.keyCodeToKeyEventCode(keyCode);
if (keyEventCode != KeyEvent.KEYCODE_UNKNOWN) { if (keyEventCode != KeyEvent.KEYCODE_UNKNOWN) {
sendDownUpKeyEventWithMetaState(keyEventCode, event.getMMetaState()); sendDownUpKeyEventWithMetaState(keyEventCode, event.getMMetaState());
return; return;
} }
// unknown event // unknown event
Log.e(TAG, "unknown event, key code: "+keyCode+", functional: "+event.isFunctionalKeyEvent()+", meta: "+event.getMMetaState()); Log.e(TAG, "unknown event, key code: "+keyCode+", meta: "+event.getMMetaState());
if (DebugFlags.DEBUG_ENABLED) if (DebugFlags.DEBUG_ENABLED)
throw new RuntimeException("Unknown event"); throw new RuntimeException("Unknown event");
} }