This fixes a problem in Android key event handling where, because I was only using a single bool to indicate that we were re-dispatching, there was a race condition when multiple keys were pending (sent to the framework, awaiting responses).
This fixes that by switching to a mechanism that uses the event itself to tell if it was redispatched.
In doing this, I realized that because key events can come from either the dispatchEvent call, or through the InputConnectionAdaptor, I needed to handle both routes properly so that the events would all be handled, and all go through the same mechanism on the framework side.
This (mostly) re-lands #21163, which was reverted in #22321
This switches from using onKeyDown to using dispatchKeyEvent on Android so that keys can be intercepted handled by the framework and not continue to be dispatched to other controls.
It also now intercepts key events sent to InputConnection.sendKeyEvent, as some IMEs do (e.g. the Hacker's Keyboard), and sends them to Flutter.
This fixes the problem where (for example) pressing TAB on a hardware keyboard sends the tab to both the text field and to the focus traversal system.
Note that we still can't intercept all keystrokes given to a soft keyboard, only those which the soft keyboard decides to send to InputConnection.sendKeyEvent, and system keys (like the back button) are only received if the IME doesn't eat them.
This re-lands #21163, which was reverted in #22004
Now that flutter/flutter#67359 has landed, this change will no longer cause spaces (and other shortcuts) to be ignored in text fields if there is no action associated with the intent, even if there is a shortcut key mapping to an intent.
It also no longer causes web test failures (as far as I can tell without submitting it: the same tests don't fail locally).
Here's the original PR description:
This switches from using dispatchKeyEvent to using dispatchKeyEventPreIme so that keys can be intercepted before they reach the IME and be handled by the framework.
It also now intercepts key events sent to InputConnection.sendKeyEvent, as some IMEs do (e.g. the Hacker's Keyboard), and sends the to Flutter before sending them to the IME (which it now only does if they are not handled by the framework).
This fixes the problem where pressing TAB on a hardware keyboard sends the tab to both the text field and to the focus traversal system.
Note that we still can't intercept all keystrokes given to a soft keyboard, only those which the soft keyboard decides to send to InputConnection.sendKeyEvent.
This re-lands #21163, which was reverted in #21513
Now that flutter/flutter#67359 has landed, this change will no longer cause spaces (and other shortcuts) to be ignored in text fields if there is no action associated with the intent, even if there is a shortcut key mapping to an intent.
Here's the original PR description:
This switches from using dispatchKeyEvent to using dispatchKeyEventPreIme so that keys can be intercepted before they reach the IME and be handled by the framework.
It also now intercepts key events sent to InputConnection.sendKeyEvent, as some IMEs do (e.g. the Hacker's Keyboard), and sends the to Flutter before sending them to the IME (which it now only does if they are not handled by the framework).
This fixes the problem where pressing TAB on a hardware keyboard sends the tab to both the text field and to the focus traversal system.
Note that we still can't intercept all keystrokes given to a soft keyboard, only those which the soft keyboard decides to send to InputConnection.sendKeyEvent.
This switches from using dispatchKeyEvent to using dispatchKeyEventPreIme so that keys can be intercepted before they reach the IME and be handled by the framework.
It also now intercepts key events sent to InputConnection.sendKeyEvent, as some IMEs do (e.g. the Hacker's Keyboard), and sends the to Flutter before sending them to the IME (which it now only does if they are not handled by the framework).
This fixes the problem where pressing TAB on a hardware keyboard sends the tab to both the text field and to the focus traversal system.
Note that we still can't intercept all keystrokes given to a soft keyboard, only those which the soft keyboard decides to send to InputConnection.sendKeyEvent.
This re-lands the key event synthesis implementation for Android (Original PR: #19024, Revert PR: #19956). The only difference is sending the synthesized key events to the root view instead of the current view.
Without sending it to the root view, the system doesn't have any chance of handling keys like the back button. The event will still not be sent to the framework twice, since we turn off event propagation while re-dispatching the event.
This implements the design in flutter.dev/go/handling-synchronous-keyboard-events for Android.
I started with Android, but this will be used for all platforms as we add them.
The related framework PR is: flutter/flutter#59358 (which has already landed)