5package io.flutter.embedding.android;
7import android.view.KeyCharacterMap;
9import androidx.annotation.NonNull;
11import io.flutter.embedding.engine.systemchannels.KeyEventChannel;
12import io.flutter.embedding.engine.systemchannels.KeyboardChannel;
13import io.flutter.plugin.common.BinaryMessenger;
14import io.flutter.plugin.editing.InputConnectionAdaptor;
15import io.flutter.plugin.editing.TextInputPlugin;
16import java.util.HashSet;
47 private static final String TAG =
"KeyboardManager";
57 private int combiningCharacter = 0;
85 char complexCharacter = (char) newCharacterCodePoint;
86 boolean isNewCodePointACombiningCharacter =
87 (newCharacterCodePoint & KeyCharacterMap.COMBINING_ACCENT) != 0;
88 if (isNewCodePointACombiningCharacter) {
90 int plainCodePoint = newCharacterCodePoint & KeyCharacterMap.COMBINING_ACCENT_MASK;
91 if (combiningCharacter != 0) {
92 combiningCharacter = KeyCharacterMap.getDeadChar(combiningCharacter, plainCodePoint);
94 combiningCharacter = plainCodePoint;
99 if (combiningCharacter != 0) {
100 int combinedChar = KeyCharacterMap.getDeadChar(combiningCharacter, newCharacterCodePoint);
101 if (combinedChar > 0) {
102 complexCharacter = (char) combinedChar;
104 combiningCharacter = 0;
108 return complexCharacter;
119 this.viewDelegate = viewDelegate;
183 private class PerEventCallbackBuilder {
185 boolean isCalled =
false;
188 public void onKeyEventHandled(
boolean canHandleEvent) {
190 throw new IllegalStateException(
191 "The onKeyEventHandledCallback should be called exactly once.");
195 isEventHandled |= canHandleEvent;
196 if (unrepliedCount == 0 && !isEventHandled) {
197 onUnhandled(keyEvent);
202 PerEventCallbackBuilder(@NonNull KeyEvent keyEvent) {
203 this.keyEvent = keyEvent;
206 final KeyEvent keyEvent;
208 boolean isEventHandled =
false;
210 public Responder.OnKeyEventHandledCallback buildCallback() {
216 private final HashSet<KeyEvent> redispatchedEvents =
new HashSet<>();
221 final boolean isRedispatchedEvent = redispatchedEvents.remove(keyEvent);
222 if (isRedispatchedEvent) {
227 final PerEventCallbackBuilder callbackBuilder =
new PerEventCallbackBuilder(keyEvent);
229 primaryResponder.handleEvent(keyEvent, callbackBuilder.buildCallback());
232 onUnhandled(keyEvent);
239 final int remainingRedispatchCount = redispatchedEvents.size();
240 if (remainingRedispatchCount > 0) {
243 "A KeyboardManager was destroyed with "
244 + String.valueOf(remainingRedispatchCount)
245 +
" unhandled redispatch event(s).");
249 private void onUnhandled(@NonNull KeyEvent keyEvent) {
254 redispatchedEvents.add(keyEvent);
256 if (redispatchedEvents.remove(keyEvent)) {
257 Log.
w(TAG,
"A redispatched key event was consumed before reaching KeyboardManager");
static void w(@NonNull String tag, @NonNull String message)
Map< Long, Long > getPressedState()
Character applyCombiningCharacterToBaseCharacter(int newCharacterCodePoint)
boolean handleEvent(@NonNull KeyEvent keyEvent)
KeyboardManager(@NonNull ViewDelegate viewDelegate)
final Responder[] responders
Map< Long, Long > getKeyboardState()
void setKeyboardMethodHandler(@Nullable KeyboardMethodHandler keyboardMethodHandler)
void onKeyEventHandled(boolean canHandleEvent)
void handleEvent( @NonNull KeyEvent keyEvent, @NonNull OnKeyEventHandledCallback onKeyEventHandledCallback)
BinaryMessenger getBinaryMessenger()
void redispatch(@NonNull KeyEvent keyEvent)
boolean onTextInputKeyEvent(@NonNull KeyEvent keyEvent)
std::function< void(MTLRenderPipelineDescriptor *)> Callback