toyota-connected / ivi-homescreen

Embedded Flutter runtime targeting Embedded Linux with Wayland

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

ivi-homescreen does not support keyboard repeat

WAKazuyoshiAkiyama opened this issue · comments

@jwinarske
I tried to run my app to check the ivi-homescreen's features related to input envents, but, my app have not worked correctly.
It seems ivi-homescreen cannot accept any keyboard events at least.

The behavior of my app is the following.

  • When the up half of the window is clicked, the mid bar will become blue to indicate that the up half takes focus.
  • While the up half takes focus, TextField will start to work.
  • When A or B key is pressed, some messages like [A_KeyDown][A_Repeat][A_KeyUp] will be output in the low half of the window.
  • When other keys is pressed, a character of a pressed key is visible in TextField.

When I use the official linux-desktop device, the app worked correctly, but, when I use ivi-homescreen for Desktop, even if I press any keys, the app has no reaction for any keys.

Please see the video.

How can I use keyboard inputs in ivi-homescreen? OR, keyboard inputs is the missing feature of ivi-homescreen?

SIDE NOTES:
ivi-homescreen causes core-dump when it is interrupted by Ctrl-C.

$ ~/homescreen --a=build/flutter_assets
[INFO:display.cc(50)] agl_shell extension not present
[INFO:display.cc(280)] Pointer Present
[INFO:display.cc(289)] Keyboard Present
[INFO:engine.cc(200)] Runtime=debug
[INFO:engine.cc(91)] flutter: The Dart VM service is listening on http://127.0.0.1:42187/ufLHlW6rddA=/
[INFO:navigation.cc(33)] Navigation: Select Single Entry History
[INFO:navigation.cc(47)] Navigation: Route Information Updated
	location: /
	state: 
	replace: 0
dddddddddddddddaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbb^C[FATAL:flutter/fml/thread_local.cc(30)] Check failed: false. pthread_setspecific failed (22): Invalid argument
[1]    28678 abort (core dumped)  ~/homescreen --a=build/flutter_assets

The only test case I have for keyboard is the Flutter Gallery app. Last I checked, that was working fine. Repeat doesn't work. If you have a test case I can repro with I'll take a look

@jwinarske
My test case is the following manual procedure.

  1. Click the up half of the app. If the mid bar becomes blue, it is OK.
  2. Long Press "a". If the messages are shown in the down half of the app, it is OK.
  3. Long Press "d". If "d" are shown repeatedly in the up half of the app, it is OK.
  4. Long Press "b", if the messages are shown in the down half of the app, it is OK.
  5. Long Press "f". If "f" are shown repeatedly in the up half of the app, it is OK.

If you mean you would like the test driver of the app, I have no test driver now.

Okay, I'll try that out tomorrow.

NOTE:

  • I used flutter v3.0.1 stable.
  • My cmake args of ivi-homescreen is cmake .. -DCMAKE_STAGING_PREFIX=pwd/out/usr/local -DBUILD_PLUGIN_TEXT_INPUT=ON
  • flutter engine rev: caaafc5604ee9172293eb84a381be6aadd660317
  • flutter engine build flag:
./flutter/tools/gn \
      --no-goma \
      --no-lto \
      --stripped \
      --no-full-dart-sdk \
      --runtime-mode debug \
      --embedder-for-target \
      --enable-fontconfig \
      --target-os linux \
      --disable-desktop-embeddings --linux-cpu x64

For 3.x and x86_64 desktop builds there is a known segfault issue. We escalated this yesterday: flutter/flutter#106118

It does not segfault on aarch64.

Until 3.x issue is resolved we should use 2.10.5 for desktop.

@jwinarske
I checked my app on flutter v2.10.5.
Key pressing can be accepted, but Long key pressing cannot be handled properly.
Please see the video.

Keys, "a", "d", "b", "f" are visible in the up half(TextField), but correctly, "a" and "b" should not be visible in the up half, and they should output the messages in the bottom half instead of it, but, actually, the messages are not output, and then, "a" and "b" are visible in the up half.

https://github.com/WAKazuyoshiAkiyama/flutter_textpad/blob/main/lib/main.dart#L48-L87

Therefore, it seems the above code cannot work correctly on ivi-homescreen.

And also, when I check the default flutter app created by flutter create, I found the difference behavior between the official linux-desktop.

On the official linux-desktop, even if I long press the left click and I move the mouse cursor on the floating button, the counter would not be updated.

Please see the video.

However, on ivi-homescreen, if I long press the left click and I move the mouse cursor on the floating button, the counter would be updated every moving.

Please see the video.

From these behavior, I think ivi-homescreen has some issues about LongPress Input events.

Could you check the above issues?

@WAKazuyoshiAkiyama I checked in fix for 3.x segfault. #58

I will get to this issue Friday (I hope); I came down with COVID on Monday.

@jwinarske
OK, I will re-check on v3.0.1 after my local repo is updated.
But, perhaps, the issue of long pressing will still happen if using v3.0.1, so please check the issue on your side.

@WAKazuyoshiAkiyama I just took a quick look. The only event I'm currently handling is the press event. I haven't sorted out repeat yet. I would expect I would just get subsequent callbacks from wayland based on the repeat time, but it doesn't. I was avoiding rolling my own repeat with timer and thread. Like start thread timer on press, and kill thread on release.

Unfortunately, SEGV has still been caused in my environment.

$ ~/homescreen --a=build/flutter_assets
[INFO:display.cc(50)] agl_shell extension not present
[INFO:display.cc(280)] Pointer Present
[INFO:display.cc(289)] Keyboard Present
[INFO:engine.cc(200)] Runtime=debug
[INFO:engine.cc(91)] flutter: The Dart VM service is listening on http://127.0.0.1:45649/7B4ycY-uMbU=/
[INFO:navigation.cc(33)] Navigation: Select Single Entry History
[INFO:navigation.cc(47)] Navigation: Route Information Updated
	location: /
	state: 
	replace: 0
^C^C^C^C^C^C[FATAL:flutter/fml/thread_local.cc(30)] Check failed: false. pthread_setspecific failed (22): Invalid argument
[1]    8868 abort (core dumped)  ~/homescreen --a=build/flutter_assets

When using v3.0.1, ivi-homescreen cannot accept any keyboard events, and SEGV happens when ivi-homescreen is interrupted by Ctrl-C.

@jwinarske I took a quick glance at GDK to see how it handles keyboard repeat and it seems to be done by registering this callback_listener https://github.com/GNOME/gtk/blob/main/gdk/wayland/gdkdevice-wayland.c#L2258

@WAKazuyoshiAkiyama Looking at the Key Repeat section here: https://wayland-book.com/seat/keyboard.html suggests we should get a repeat event, if seat interface version >= 4. I'm requesting minimum of 5. I never see the event. It also mentions you use this event to setup your repeat timer delay. If I have a machine that gives me the repeat event I can implement repeat. This is on Ubuntu 20.4.4 LTS.

@WAKazuyoshiAkiyama Okay I dropped version to 4, and I get the repeat event. I'll look into adding repeat over the next week.

@jwinarske If it's helpful, I'm happy to take a crack at implementing keyboard repeat. It's my understanding that repeat_info event is only for configuring the repeat settings delay threshold and repeat rate right? It's the wayland client's responsibility to implement the repeat. Another data point is that similar to GDK, Chromium's ozone sets up a repeat callback: https://chromium.googlesource.com/chromium/src/+/efa8b4ba79261a1d84faaf382a25e01f7fc6210f/ui/ozone/platform/wayland/wayland_keyboard.h#87

@jwinarske
I asked my colleague (@pfpacket) to let me know a good sample for wl_keyboard handling, and then he give me the link https://gitlab.freedesktop.org/wayland/weston/-/blob/main/clients/window.c#L3299.
If it is helpful, I would be happy.

@WAKazuyoshiAkiyama please feel free to submit PR. Like i said you just change seat interface version to 4 to get the repeat event; it's currently on 5.

Let @pfpacket know I'm making progress on upstreaming his work to OpenCV. It's very close now, next is to run validation builds in Yocto.
opencv/opencv#22102
Once it is part of a release i will send patch to oe-core.

@jwinarske

please feel free to submit PR. Like i said you just change seat interface version to 4 to get the repeat event; it's currently on 5.

Yeah, I will try to implement.

Let @pfpacket know I'm making progress on upstreaming his work to OpenCV. It's very close now, next is to run validation builds in Yocto.
opencv/opencv#22102
Once it is part of a release i will send patch to oe-core.

He was aware of this, so we talked about this.

@doesnotexist Omar I am working on a branch that allows selecting between Vulkan and EGL (build time). I could use some eyes on that. The goal is to extend backends to others. See the jw/vulkan branch. I haven't tested out if EGL texture widgets work in conjunction with Vulkan. I'm skeptical as I haven't seen any interop code. Another item is libcamera integration with Flutter 1P Camera Plugin.

https://gitlab.freedesktop.org/wayland/weston/-/blob/main/clients/window.c#L3226-3238
It seems these codes handle the key repeating.
If the key is pressed, the timerfd based timer will be started (https://gitlab.freedesktop.org/wayland/weston/-/blob/main/clients/window.c#L3238).
If the key is released, the timer will be finished (https://gitlab.freedesktop.org/wayland/weston/-/blob/main/clients/window.c#L3228).

For keyboard events, when the timer is fired, keyboard_repeat_func is called.
https://gitlab.freedesktop.org/wayland/weston/-/blob/main/clients/window.c#L5941

https://gitlab.freedesktop.org/wayland/weston/-/blob/main/clients/window.c#L3008
https://gitlab.freedesktop.org/wayland/weston/-/blob/main/clients/window.c#L4745
https://gitlab.freedesktop.org/wayland/weston/-/blob/main/clients/editor.c#L1656

keyboard_repeat_func seems to execute a callback registered on a client app side.

From my understanding, in the case of ivi-homescreen, this callback is not different per apps i.e. ivi-homescreen will have an unified callback for all flutter app, to notify keyboard events to FlutterEngine. The callback should be provided by the TextInput plugin.

In the above samples, the timer is implemented with timerfd, but, from my memory, FlutterEngine may provide a dedicated timer feature for an embedder.

@jwinarske
Is my above understanding correct? If so, could you tell me how to use the timer provided by FlutterEngine? Or, if I should implement a specific timer based on timerfd, please let me know.

I apologize for joining in, feel free to disregard my input here if it isn't helpful, this topic interests me as well and perhaps what I researched can be helpful.

@WAKazuyoshiAkiyama what you describe regarding timers and callbacks to implement keyboard repeat is consistent with my understanding. But I can't say whether FlutterEngine provides a specific mechanism for embedders. A quick look around I do see some TaskRunner concept and there is of course the main event loop (FML I think it is) but the other shell's rely on their underlying platform event loop not Flutters task runners/event loop. For example on linux desktop the shell hooks into the Glib main event loop.

Based on how GDK/wayland keyboard repeat implementation works it appears you can just piggy back on wayland's event loop, running your callback by adding it to run after each wl_display_sync. Otherwise, perhaps you could just use a system specific standard library timer to implement this feature. For ivi-homescreen project it's unclear to me whether that should be pthread's timer_create/timer_settime or to use c++ std::thread and std::chrono?

@jwinarske should probably weigh in as to which implementation choice is the preferred way forward for this embedder.

Also, just wanted to point out that it appears that it is the expectation that the embedder emits a kFlutterKeyEventTypeRepeat on detecting a platform keyboard repeat event:
https://github.com/flutter/engine/blob/main/shell/platform/embedder/embedder.h#L819

@WAKazuyoshiAkiyama I started a branch for you based on my interpretation of window.c:
https://github.com/toyota-connected/ivi-homescreen/tree/feature/keyb_repeat

The missing part is a simple generic timer with callback. Whichever implementation, it should not bring in any unnecessary dependencies. Smallest and most elegant is preferred.

I added TODO comments in the source where timer state changes need to happen; I may have missed one.

Let's start with this.

@WAKazuyoshiAkiyama I think we pull in platform/linux/timerfd.h, and platform/linux/timerfd.cc from the flutter engine repo. I'll update the branch.

@WAKazuyoshiAkiyama Actually just use <sys/timerfd.h>. That will be fine.

Just read this section in the wayland book about using the wayland event loop
https://wayland-book.com/wayland-display/event-loop.html

Which led me to investigate the wl_event_loop_add_timer() which really just wraps timerfd_create()
https://chromium.googlesource.com/external/wayland/wayland/+/refs/heads/master/src/event-loop.c#189
https://chromium.googlesource.com/external/wayland/wayland/+/refs/heads/master/src/wayland-server-core.h#68

I wonder if thats appropriate or not, the documentation is a little confusing about where in the wayland stack you're meant to be using the wl_event_loop interface, and I must admit that I'm little confused about how best to think about ivi-homescreen in terms of the wayland stack, would it be equivalent to a compositor like sway or weston? Since sway seems to use wl_event_loop_add_timer() for this purpose
https://github.com/swaywm/sway/blob/master/sway/input/keyboard.c#L710

Or is it that in production systems https://gitlab.com/automotivegradelinux/src/agl-compositor the intended compositor?

@doesnotexist

I like the idea of keeping common Wayland calls if possible, that's a plus. On the minus side it adds a new library dependency - wayland-server. I would want to avoid pulling that in.

We're sticking with timerfd.

At least, I added the feature to handle the long press event, but somewhy, the behavior of A and B key are different from the official linux desktop embedder.
So, currently, I am investigating why such behavior difference is caused.

At least, I added the feature to handle the long press event, but somewhy, the behavior of A and B key are different from the official linux desktop embedder.

A and B key specific events of flutter_textpad are done if a key event is a logical key event.
https://github.com/WAKazuyoshiAkiyama/flutter_textpad/blob/main/lib/main.dart#L49-L60

https://github.com/toyota-connected/ivi-homescreen/blob/main/third_party/flutter/flutter_embedder.h#L683-L746
So, in the flutter official linux desktop embedder, the above "logical" member may be set.

From my understanding, to make the key event behavior same as the official embedder, the code to transform phycial key events to logical key events and the code to set the "logical" member of FlutterKeyEvent need to be implemented.
To my mind, the former one should be implemented in display.cc and the latter one should be implemented in text_input.cc.
Especially, for the former one, I have no concrete implementation image. Maybe I might need to add the implementation about keymap and xkb_compose, but I'm not sure.

And also, FlutterKeyEvent doesn't appear under shell/. So, I haven't decided how to implement those codes...

Or rather, text_input plugin needs to be re-implemented with using https://github.com/toyota-connected/ivi-homescreen/blob/main/third_party/flutter/flutter_embedder.h#L1768-L1773 ?

@jwinarske
Could you give me your opinions about how to handle logical/phycal key events in ivi-homescreen?

@WAKazuyoshiAkiyama I think I missed the distinction between text_input and raw keyboard event handling. So, my mentioning FlutterKeyEvent previously may have been a bit misleading since we were talking about text_input specifically. You are right, this embedder never calls m_proc_table.SendKeyEvent() so currently FlutterKeyEvents are not used.

FlutterKeyEvents, seem to be for keyboard events outside of the text_input plugin, and should probably be handled along side text_input within keyboard_handle_key() in display.cc
https://github.com/toyota-connected/ivi-homescreen/blob/main/shell/display.cc#L502

Looking at the framework (dart) side, there are a few different consumers of TextInput update events that are ultimately sent on the 'flutter/textinput' channel. For non text input keyboard events, I think those are meant to be packaged in struct FlutterKeyEvent and sent by the m_proc_table.SendKeyEvent. Which I think should just be a function pointer to the engine's embedder implementation FlutterEngineSendKeyEvent https://github.com/flutter/engine/blob/main/shell/platform/embedder/embedder.cc#L1873
and that just repackages those FlutterKeyEvents into as KeyDataPackets to send them over a channel called 'flutter/keydata':

Thats my understanding, but I could be wrong. If thats correct, then I think there is work to be done within keyboard_handle_key() in display.cc to support the FlutterKeyEvent/non text_input path. But keeping in mind that a key event could also be destined for the text_input plugin. Not sure but it looks like for linux desktop an event goes down one path or the other, but glfw just broadcasts a keyboard input event down both, not 100% sure.

Personally for my use-cases, I'm not using any widgets that are TextInput client's but I would like to have keyboard navigation when no mouse or pointer is available and for accessibility. I'm hoping that supporting raw keyboard events would enable that. Since text_input is separate, you may not want to bother with the KeyEvent stuff if you only need to use TextInput clients.

** Disclaimer: I'm new to all this and just trying to learn how it all fits together, so take my input (no pun intended) with a grain of salt.

@WAKazuyoshiAkiyama I suspect that the Container where you handle key events would be a consumer of the KeyEvent's sent over by m_proc_table.SendKeyEvent() but your TextField should be a consumer of TextInput since it wraps an EditableText widget. Perhaps no text input is getting to the textfield since the Container is autofocus'd and ivi-homescreen currently doesn't send any keyboard input except to text input clients. If you put the focus on the text field, I think you'll get some keyboard input but no keyboard repeat behavior. https://docs.flutter.dev/cookbook/forms/focus

@doesnotexist
Thank you for your comments.

Especially, #54 (comment) is helpful for me.
Anyway, I will think how to implement the KeyEvent handling code in keyboard_handle_key() in display.cc.

@jwinarske
In order to convert xkb keys/syms to FlutterLogical/PhycalKey, the following files are required.

At least, xkb_to_physical_key_map is required.

https://github.com/flutter/engine/blob/main/shell/platform/linux/fl_key_embedder_responder.cc#L740
https://github.com/flutter/engine/blob/main/shell/platform/linux/fl_key_embedder_responder.cc#L710
https://github.com/flutter/engine/blob/main/shell/platform/linux/fl_key_embedder_responder.cc#L297

The above codes are related to convert xkb keys to physical keys.

For logical keys, maybe, it can be gotten with xkb_keysym_to_utf32, so it is not a big problem.

I will create a file corresponding to key_mappning.cc, but, I'm not sure where I should place that file.
Which should I place the file under shell/ or third_party/flutter?

And also, key_mapping.cc seems to be automatically generated.

https://github.com/flutter/engine/blob/main/shell/platform/linux/key_mapping.g.cc#L12-L18

But, as a start, I will create the file manually. Is it OK?

@WAKazuyoshiAkiyama

/shell/platform/linux/key_mapping.h would go into:
https://github.com/toyota-connected/ivi-homescreen/tree/main/third_party/flutter/shell/platform/linux
Be sure to comment out GTK/glib deps to make rebase work easier.

For implementation port from GTK (.g.cc) that can go under:
https://github.com/toyota-connected/ivi-homescreen/tree/main/shell/static_plugins/text_input

Yes manual is what we want.

I implemented the code to send a key event with SendKeyEvent defined in flutter_embedder.h.
But, unfortunately, flutter_textpad seems not to accept any KeyUp/Down/Repeat Event.

https://github.com/sony/flutter-embedded-linux/blob/master/src/flutter/shell/platform/linux_embedded/plugins/key_event_plugin.cc#L120-L140

I checked the sony's embedder and flutter_textpad's code to handle A key worked on the sony's one.
In the sony's one, BasicMessageChannel.Send() is used instead of SendKeyEvent().

So, I will try to create fl_key_event.cc to provide class KeyEvent to send key event message through the "flutter/keyevent" channel and composite that class to class Display.

Oh hrmm, thats interesting. Yeah, so 'flutter/keyevent' vs 'flutter/keydata' is confusing and I'm not exactly sure whats what.
See this comment about 'flutter/keydata'

// Not to be confused with "flutter/keyevent", which is used to send raw
// key event data in a platform-dependent format.

https://github.com/flutter/engine/blob/main/shell/platform/embedder/embedder.cc#L73-L93

Also check this part of the framework out, it seems to receive on 'flutter/keyevent' (also, grep'ing the framework returns no results for 'flutter/keydata' which is curious) but the comment above this function says that 'flutter/keyevent' is only used on Android and Fuschia at the moment:
https://github.com/flutter/flutter/blob/master/packages/flutter/lib/src/services/system_channels.dart#L225-L246

Then there is this portion inside of the Android code that seems to receive events on 'flutter/keyevent' and then translate them into KeyDataPackets which is equivalent to the process in FlutterEngineSendKeyEvent()
https://github.com/flutter/engine/blob/main/shell/platform/android/io/flutter/embedding/android/KeyEmbedderResponder.java#L254

I'm currently traveling but if I get some time, I'll try to set up ivi-homescreen on the road and see if I can give it a spin too.

So, I will try to create fl_key_event.cc to provide class KeyEvent to send key event message through the "flutter/keyevent" channel and composite that class to class Display.

I found I need to create a new static_plugins "key_event" instead of fl_key_event.cc like text_input.

I implemented static_plugins/key_event/key_event.cc to send a key event message through "flutter/keyevent".

Somewhy, the following exception is thrown, but, at least, flutter_textpad can accept KeyUp/Down/Repeat events.

I need to brash up my source codes...but, our direction is correct.

Thank you @doesnotexist !

[ERROR:flutter/lib/ui/ui_dart_state.cc(209)] Unhandled Exception: 'package:flutter/src/services/hardware_keyboard.dart': Failed assertion: line 787 pos 16: 'false': Should never encounter KeyData when transitMode is rawKeyData.
#0      _AssertionError._doThrowNew (dart:core-patch/errors_patch.dart:51:61)
#1      _AssertionError._throwNew (dart:core-patch/errors_patch.dart:40:5)
#2      KeyEventManager.handleKeyData (package:flutter/src/services/hardware_keyboard.dart:787:16)
#3      PlatformDispatcher._keyDataListener.<anonymous closure>.<anonymous closure> (dart:ui/platform_dispatcher.dart:394:41)
#4      _invoke1 (dart:ui/hooks.dart:168:13)
#5      PlatformDispatcher._keyDataListener.<anonymous closure> (dart:ui/platform_dispatcher.dart:392:7)
#6      _invoke2.<anonymous closure> (dart:ui/hooks.dart:190:15)
#7      _rootRun (dart:async/zone.dart:1426:13)
#8      _CustomZone.run (dart:async/zone.dart:1328:19)
#9      _CustomZone.runGuarded (dart:async/zone.dart:1236:7)
#10     _invoke2 (dart:ui/hooks.dart:189:10)
#11     _ChannelCallbackRecord.invoke (dart:ui/channel_buffers.dart:42:5)
#12     _Channel.push (dart:ui/channel_buffers.dart:132:31)
#13     ChannelBuffers.push (dart:ui/channel_buffers.dart:329:17)
#14     PlatformDispatcher._dispatchPlatformMessage (dart:ui/platform_dispatcher.dart:583:22)
#15     _dispatchPlatformMessage (dart:ui/hooks.dart:89:31)
Flutter.Textpad_Flutter2.10.5_WIP_RawKeyEvent_Trim.mp4

@WAKazuyoshiAkiyama Heads up I just merged multiple backend support; it's a big change.

I fixed the dart exception.
And, there is a issue that any function keys are not available, but I have already fixed it.
KeyEvent's key code needs to be converted with the table like https://github.com/sony/flutter-embedded-linux/blob/master/src/flutter/shell/platform/linux_embedded/plugins/keyboard_glfw_util.cc#L188.
I implemented the convert table with using https://github.com/sony/flutter-embedded-linux/blob/master/src/flutter/shell/platform/linux_embedded/plugins/keyboard_glfw_util.cc#L188 as the reference.

So, the remained issue is that the cursor of TextField unintentionally moves to a head of a line when A key is pressed.

Maybe, https://github.com/sony/flutter-embedded-linux/blob/master/src/flutter/shell/platform/linux_embedded/plugins/key_event_plugin.cc#L85 and/or https://github.com/sony/flutter-embedded-linux/blob/master/src/flutter/shell/platform/linux_embedded/flutter_elinux_view.cc#L216 can be used as the reference.

Actually, handling A key in OnKeyEvent of flutter is just a sample implementation and I guess in most cases, what keys are handled in OnKeyEvent is a key like Function keys or modifier keys, so, I think by letting TextInput ignore some keys, this issue can be solved...

@jwinarske
Do you know how to receive the response from flutter engine(app)?

For the issue that the cursor of TextField unintentionally moves to a head of a line when key "a" is pressed, I checked this behavior on sony's embedder and the official linux desktop.

The issue happens on sony's one also, but does not happen on the official one.
In the official one, the keys handled by OnKeyEvent of flutter app (e.g. "a") don't appear in TextField.
So, I think the procedures like the following are required.

  1. KeyEvent sends a key event to FlutterEngine via "flutter/keyevent" channel.
  2. KeyEvent receives a response from FlutterEngine and checks if a sent event is handled. (ref: https://github.com/WAKazuyoshiAkiyama/flutter_textpad/blob/main/lib/main.dart#L53)
  3. If a sent event is not handled, KeyEvent will call TextInput::keyboard_handle_key. If a sent event is handled, TextInput::keyboard_handle_key will be skipped.

I registered KeyEvent::OnPlatformMessage, but, this callback seems not be called when KeyEvent sends a key event to Engine.
So, currently, I have no way to receive any responses related to "flutter/keyevent" from Engine.
Therefore, if you know how to receive a response from Engine, could you teach me it?

@WAKazuyoshiAkiyama The only way to receive a response from app is via platform channels, or implement custom interface using FFI. I recall some of the engine keyboard source expects to link directly to the engine, which interfaces are not exposed in flutter_embedder.h. I looked at flutter/keyevent a long time ago, and never saw it propagate to platform channel; having asked Stuart Morgan on the subject he pointed me to the current model I have implemented. Can you point me to your working branch?

I would like to merge the keyboard auto-repeat changes independent from the text plugin changes.