enable hardware keyboard handling again, with improved handling

This commit is contained in:
Helium314 2025-06-14 11:29:26 +02:00
parent 63dad1549e
commit a37de668c0
5 changed files with 86 additions and 87 deletions

View file

@ -256,11 +256,9 @@ class Event private constructor(
source.mX, source.mY, source.mSuggestedWordInfo, source.mFlags or FLAG_COMBINING, source.mNextEvent) source.mX, source.mY, source.mSuggestedWordInfo, source.mFlags or FLAG_COMBINING, source.mNextEvent)
} }
fun createNotHandledEvent(): Event { val notHandledEvent = Event(EVENT_TYPE_NOT_HANDLED, null, NOT_A_CODE_POINT, NOT_A_KEY_CODE, 0,
return Event(EVENT_TYPE_NOT_HANDLED, null, NOT_A_CODE_POINT, NOT_A_KEY_CODE, 0,
Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, null, FLAG_NONE, null) Constants.NOT_A_COORDINATE, Constants.NOT_A_COORDINATE, null, FLAG_NONE, null)
} }
}
// This method is private - to create a new event, use one of the create* utility methods. // This method is private - to create a new event, use one of the create* utility methods.
init { init {

View file

@ -48,6 +48,8 @@ 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 Event.createNotHandledEvent() } else {
Event.notHandledEvent
}
} }
} }

View file

@ -210,12 +210,54 @@ object KeyCode {
// todo: there are many more keys, see near https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_0 // todo: there are many more keys, see near https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_0
/** /**
* Convert a keyCode / codePoint to a KeyEvent.KEYCODE_<xxx>. * Convert an internal keyCode to a KeyEvent.KEYCODE_<xxx>.
* Positive codes are passed through, unknown negative codes result in KeyEvent.KEYCODE_UNKNOWN.
* To be uses for fake hardware key press.
*/
@JvmStatic fun keyCodeToKeyEventCode(keyCode: Int) = when (keyCode) {
ARROW_UP -> KeyEvent.KEYCODE_DPAD_UP
ARROW_RIGHT -> KeyEvent.KEYCODE_DPAD_RIGHT
ARROW_DOWN -> KeyEvent.KEYCODE_DPAD_DOWN
ARROW_LEFT -> KeyEvent.KEYCODE_DPAD_LEFT
MOVE_START_OF_LINE -> KeyEvent.KEYCODE_MOVE_HOME
MOVE_END_OF_LINE -> KeyEvent.KEYCODE_MOVE_END
TAB -> KeyEvent.KEYCODE_TAB
PAGE_UP -> KeyEvent.KEYCODE_PAGE_UP
PAGE_DOWN -> KeyEvent.KEYCODE_PAGE_DOWN
ESCAPE -> KeyEvent.KEYCODE_ESCAPE
INSERT -> KeyEvent.KEYCODE_INSERT
SLEEP -> KeyEvent.KEYCODE_SLEEP
MEDIA_PLAY -> KeyEvent.KEYCODE_MEDIA_PLAY
MEDIA_PAUSE -> KeyEvent.KEYCODE_MEDIA_PAUSE
MEDIA_PLAY_PAUSE -> KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
MEDIA_NEXT -> KeyEvent.KEYCODE_MEDIA_NEXT
MEDIA_PREVIOUS -> KeyEvent.KEYCODE_MEDIA_PREVIOUS
VOL_UP -> KeyEvent.KEYCODE_VOLUME_UP
VOL_DOWN -> KeyEvent.KEYCODE_VOLUME_DOWN
MUTE -> KeyEvent.KEYCODE_VOLUME_MUTE
BACK -> KeyEvent.KEYCODE_BACK
F1 -> KeyEvent.KEYCODE_F1
F2 -> KeyEvent.KEYCODE_F2
F3 -> KeyEvent.KEYCODE_F3
F4 -> KeyEvent.KEYCODE_F4
F5 -> KeyEvent.KEYCODE_F5
F6 -> KeyEvent.KEYCODE_F6
F7 -> KeyEvent.KEYCODE_F7
F8 -> KeyEvent.KEYCODE_F8
F9 -> KeyEvent.KEYCODE_F9
F10 -> KeyEvent.KEYCODE_F10
F11 -> KeyEvent.KEYCODE_F11
F12 -> KeyEvent.KEYCODE_F12
else -> if (keyCode < 0) KeyEvent.KEYCODE_UNKNOWN else keyCode
}
// todo: there are many more keys, see near https://developer.android.com/reference/android/view/KeyEvent#KEYCODE_0
/**
* Convert a codePoint to a KeyEvent.KEYCODE_<xxx>.
* Fallback to KeyEvent.KEYCODE_UNKNOWN. * Fallback to KeyEvent.KEYCODE_UNKNOWN.
* To be uses for fake hardware key press. * To be uses for fake hardware key press.
* */ */
fun Int.toKeyEventCode(): Int = if (this > 0) @JvmStatic fun codePointToKeyEventCode(codePoint: Int): Int = when (codePoint.toChar().uppercaseChar()) {
when (this.toChar().uppercaseChar()) {
'/' -> KeyEvent.KEYCODE_SLASH '/' -> KeyEvent.KEYCODE_SLASH
'\\' -> KeyEvent.KEYCODE_BACKSLASH '\\' -> KeyEvent.KEYCODE_BACKSLASH
';' -> KeyEvent.KEYCODE_SEMICOLON ';' -> KeyEvent.KEYCODE_SEMICOLON
@ -269,40 +311,4 @@ object KeyCode {
'Z' -> KeyEvent.KEYCODE_Z 'Z' -> KeyEvent.KEYCODE_Z
else -> KeyEvent.KEYCODE_UNKNOWN else -> KeyEvent.KEYCODE_UNKNOWN
} }
else when (this) {
ARROW_UP -> KeyEvent.KEYCODE_DPAD_UP
ARROW_RIGHT -> KeyEvent.KEYCODE_DPAD_RIGHT
ARROW_DOWN -> KeyEvent.KEYCODE_DPAD_DOWN
ARROW_LEFT -> KeyEvent.KEYCODE_DPAD_LEFT
MOVE_START_OF_LINE -> KeyEvent.KEYCODE_MOVE_HOME
MOVE_END_OF_LINE -> KeyEvent.KEYCODE_MOVE_END
TAB -> KeyEvent.KEYCODE_TAB
PAGE_UP -> KeyEvent.KEYCODE_PAGE_UP
PAGE_DOWN -> KeyEvent.KEYCODE_PAGE_DOWN
ESCAPE -> KeyEvent.KEYCODE_ESCAPE
INSERT -> KeyEvent.KEYCODE_INSERT
SLEEP -> KeyEvent.KEYCODE_SLEEP
MEDIA_PLAY -> KeyEvent.KEYCODE_MEDIA_PLAY
MEDIA_PAUSE -> KeyEvent.KEYCODE_MEDIA_PAUSE
MEDIA_PLAY_PAUSE -> KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE
MEDIA_NEXT -> KeyEvent.KEYCODE_MEDIA_NEXT
MEDIA_PREVIOUS -> KeyEvent.KEYCODE_MEDIA_PREVIOUS
VOL_UP -> KeyEvent.KEYCODE_VOLUME_UP
VOL_DOWN -> KeyEvent.KEYCODE_VOLUME_DOWN
MUTE -> KeyEvent.KEYCODE_VOLUME_MUTE
BACK -> KeyEvent.KEYCODE_BACK
F1 -> KeyEvent.KEYCODE_F1
F2 -> KeyEvent.KEYCODE_F2
F3 -> KeyEvent.KEYCODE_F3
F4 -> KeyEvent.KEYCODE_F4
F5 -> KeyEvent.KEYCODE_F5
F6 -> KeyEvent.KEYCODE_F6
F7 -> KeyEvent.KEYCODE_F7
F8 -> KeyEvent.KEYCODE_F8
F9 -> KeyEvent.KEYCODE_F9
F10 -> KeyEvent.KEYCODE_F10
F11 -> KeyEvent.KEYCODE_F11
F12 -> KeyEvent.KEYCODE_F12
else -> KeyEvent.KEYCODE_UNKNOWN
}
} }

View file

@ -7,11 +7,7 @@
package helium314.keyboard.latin.define package helium314.keyboard.latin.define
object ProductionFlags { object ProductionFlags {
const val IS_HARDWARE_KEYBOARD_SUPPORTED = false const val IS_HARDWARE_KEYBOARD_SUPPORTED = true
// todo: make it work
// was set to true in hangul branch (and there is the hangul hardware event decoder in latinIme)
// but disabled again because this breaks ctrl+c / ctrl+v, and most likely other things
// so it looks like the HardwareKeyboardEventDecoder needs some work before it's ready
/** /**
* Include all suggestions from all dictionaries in * Include all suggestions from all dictionaries in

View file

@ -643,7 +643,8 @@ public final class InputLogic {
*/ */
private void handleFunctionalEvent(final Event event, final InputTransaction inputTransaction, private void handleFunctionalEvent(final Event event, final InputTransaction inputTransaction,
final String currentKeyboardScript, final LatinIME.UIHandler handler) { final String currentKeyboardScript, final LatinIME.UIHandler handler) {
switch (event.getMKeyCode()) { final int keyCode = event.getMKeyCode();
switch (keyCode) {
case KeyCode.DELETE: case KeyCode.DELETE:
handleBackspaceEvent(event, inputTransaction, currentKeyboardScript); handleBackspaceEvent(event, inputTransaction, currentKeyboardScript);
// Backspace is a functional key, but it affects the contents of the editor. // Backspace is a functional key, but it affects the contents of the editor.
@ -686,7 +687,7 @@ public final class InputLogic {
case KeyCode.SHIFT_ENTER: case KeyCode.SHIFT_ENTER:
// todo: try using sendDownUpKeyEventWithMetaState() and remove the key code maybe // todo: try using sendDownUpKeyEventWithMetaState() and remove the key code maybe
final Event tmpEvent = Event.createSoftwareKeypressEvent(Constants.CODE_ENTER, final Event tmpEvent = Event.createSoftwareKeypressEvent(Constants.CODE_ENTER,
event.getMKeyCode(), 0, event.getMX(), event.getMY(), event.isKeyRepeat()); keyCode, 0, event.getMX(), event.getMY(), event.isKeyRepeat());
handleNonSpecialCharacterEvent(tmpEvent, inputTransaction, handler); handleNonSpecialCharacterEvent(tmpEvent, inputTransaction, handler);
// Shift + Enter is treated as a functional key but it results in adding a new // Shift + Enter is treated as a functional key but it results in adding a new
// line, so that does affect the contents of the editor. // line, so that does affect the contents of the editor.
@ -777,23 +778,19 @@ public final class InputLogic {
case KeyCode.CAPS_LOCK, KeyCode.EMOJI, KeyCode.TOGGLE_ONE_HANDED_MODE, KeyCode.SWITCH_ONE_HANDED_MODE: case KeyCode.CAPS_LOCK, KeyCode.EMOJI, KeyCode.TOGGLE_ONE_HANDED_MODE, KeyCode.SWITCH_ONE_HANDED_MODE:
break; break;
default: default:
if (KeyCode.INSTANCE.isModifier(event.getMKeyCode())) if (KeyCode.INSTANCE.isModifier(keyCode))
return; // continuation of previous switch case, but modifiers are in a separate place return; // continuation of previous switch case above, but modifiers are held in a separate place
if (event.getMMetaState() != 0) { final int keyEventCode = event.getMCodePoint() <= 0
// need to convert codepoint to KeyEvent.KEYCODE_<xxx> ? KeyCode.keyCodeToKeyEventCode(keyCode)
final int codeToConvert = event.getMKeyCode() < 0 ? event.getMKeyCode() : event.getMCodePoint(); : KeyCode.codePointToKeyEventCode(event.getMCodePoint());
int keyEventCode = KeyCode.INSTANCE.toKeyEventCode(codeToConvert);
if (keyEventCode != KeyEvent.KEYCODE_UNKNOWN)
sendDownUpKeyEventWithMetaState(keyEventCode, event.getMMetaState());
return; // never crash if user inputs sth we don't have a KeyEvent.KEYCODE for
} else if (event.getMKeyCode() < 0) {
int keyEventCode = KeyCode.INSTANCE.toKeyEventCode(event.getMKeyCode());
if (keyEventCode != KeyEvent.KEYCODE_UNKNOWN) { if (keyEventCode != KeyEvent.KEYCODE_UNKNOWN) {
sendDownUpKeyEvent(keyEventCode); sendDownUpKeyEventWithMetaState(keyEventCode, event.getMMetaState());
return; return;
} }
} // unknown event
throw new RuntimeException("Unknown key code : " + event.getMKeyCode()); Log.e(TAG, "unknown event, key code: "+keyCode+", functional: "+event.isFunctionalKeyEvent()+", meta: "+event.getMMetaState());
if (DebugFlags.DEBUG_ENABLED)
throw new RuntimeException("Unknown event");
} }
} }