Repository navigation
Report hardware keyboard keys in Android TextInput onKeyPress - #59120
Open
YevheniiKotyrlo wants to merge 5 commits into
Open
YevheniiKotyrlo wants to merge 5 commits into
YevheniiKotyrlo wants to merge 5 commits into
Conversation
onKeyPress on Android is driven by ReactEditTextInputConnectionWrapper, which sees only what the input method sends through the InputConnection. A hardware keyboard's keys never pass through it: they reach the EditText through dispatchKeyEvent and the KeyListener, so an arrow, Home/End, a separator typed on a paired keyboard, or any other hardware key produced no onKeyPress at all. ReactEditText.onKeyDown now reports those keys: a key that types a character as that character, and a key that types none by its web KeyboardEvent.key value (ArrowLeft, Home, PageDown, Escape, ...). Enter and Backspace keep the names the soft keyboard path reports, a modifier on its own or a Ctrl/Meta chord is not reported, and a key event the input method sent through the InputConnection is left to the wrapper, which already reports it, so no key is reported twice.
An input method that handles a hardware keyboard forwards its keys through InputConnection.sendKeyEvent: Gboard commits the letters as text and sends arrows, Home, End and Backspace as key events. So every key event is reported where it reaches the view, ReactEditText.onKeyDown, whether a hardware keyboard or an input method sent it, and ReactEditTextInputConnectionWrapper reports only the keys an input method types as text. No key is reported twice, and keys an input method sends together are reported in the order the view receives them.
YevheniiKotyrlo
marked this pull request as ready for review
October 15, 2026 18:51
YevheniiKotyrlo
marked this pull request as draft
October 15, 2026 20:09
onKeyPress names each key by its KeyboardEvent.key value, from the key table the View key events use, and carries altKey, ctrlKey, metaKey and shiftKey. A key that types a character after a dead key is reported as the composed character, and system keys such as Back and volume are not reported. The key table follows the UI Events key values as Firefox for Android pairs them with key codes, so View onKeyDown also names Home, End, the function keys and Ctrl shortcuts instead of reporting them as Unidentified. The tests deliver an input method's key events through the window, as the framework delivers them to a focused view.
On a layout where Alt+E types no character, the key value is "e" with altKey set, as on the web, rather than Unidentified. The tests type on a layout of their own for this and for a dead key, which Robolectric's key character map cannot express.
|
Warning JavaScript API change detected This PR commits an update to
This change was flagged as: |
YevheniiKotyrlo
marked this pull request as ready for review
October 15, 2026 23:52
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary:
With a keyboard attached to an Android phone or tablet,
TextInput'sonKeyPressmisses keys, and which ones depends on the keyboard app. With Samsung Keyboard, the default on Samsung devices, nothing typed on the keyboard is reported: not letters, not Enter, not Backspace. With Gboard, letters and Backspace are reported, but arrows, Home, End and every other key are not. A code field that steps back on Backspace, or a suggestion list moved with the arrow keys, works on the web and not on Android. The docs record the limitation ("on Android only the inputs from soft keyboard are handled"), and #19507 met the same gap on the soft numeric keypad, which #29046 closed for digits only.onKeyPressonly reported what an input method types through theInputConnection. A hardware key reachesReactEditTextas a key event instead: directly with Samsung Keyboard, and throughInputConnection.sendKeyEventwith Gboard. This reports every key event fromReactEditText.onKeyDown, where both arrive, by itsKeyboardEvent.keyvalue, withaltKey,ctrlKey,metaKeyandshiftKey, asonKeyPressreports on the web. System keys (Back, volume, media) are not reported, and a character typed after a dead key is reported composed, as on the web. The input connection wrapper keeps reporting typed text, without itssendKeyEventspecial cases.The names come from the table the View
onKeyDownevent (#54308) already used, completed with the UI Events key values as Firefox for Android pairs them with key codes, soonKeyDownalso names Home, End, the function keys and Ctrl shortcuts that it reported asUnidentified.onKeyDownalone does not cover this: it is behindenableKeyEvents, and it never sees a key that Gboard types as text.Changelog:
[ANDROID] [ADDED] -
TextInputonKeyPressreports every hardware keyboard key by itsKeyboardEvent.keyvalue, withaltKey,ctrlKey,metaKeyandshiftKeyTest Plan:
ReactEditTextKeyPressTestfocuses the view in a window and sends keys the two ways a device does: to the window, as a hardware keyboard does, and through the view's input connection, which the framework delivers back to the view. Onmain10 of its 15 cases fail; with the change all pass.KeyDownEventTestfails onmainwithUnidentifiedfor Home, PageDown, Delete and F1. The ReactAndroid unit suite passes with-PenableWarningsAsErrors=true, as do Flow, both TypeScript checks, ESLint, Prettier and ktfmt, andReactNativeApi.d.tsis regenerated.RNTester release builds with the Playground below, typing a, Shift+B, Ctrl+C, ←, →, Home, End, F1, Alt+E, E, volume up, volume down, ←, Backspace and z on a USB keyboard (registered through
uinput), report:main[]a,shift+Shift,shift+B,ctrl+Control,ctrl+c,ArrowLeft,ArrowRight,Home,End,F1,alt+Alt,alt+e,e,ArrowLeft,Backspace,za,B,e,Backspace,za,shift+Shift,B,e,ctrl+Control,ctrl+c,ArrowLeft,ArrowRight,Home,End,F1,alt+Alt,alt+e,ArrowLeft,Backspace,zGboard types letters as text at once and forwards the other keys later, so the two interleave in the order Gboard delivers them. The volume keys are not reported on either device. An accent key (Alt+E in Android's virtual key map, sent with
adb shell input keycombination) reportsalt+Deadand thenéon the S23. The soft keyboard (q, Backspace, Backspace,w) and the soft numeric keypad (1,2, Backspace,3) report the same keys on both builds and both devices.packages/rn-tester/js/examples/Playground/RNTesterPlayground.js