未验证 提交 83b9df9d 编写于 作者: R Ren You 提交者: GitHub

Revert "Use dispatchKeyEventPreIme, and handle keys sent to...

Revert "Use dispatchKeyEventPreIme, and handle keys sent to InputConnection.sendKeyEvent on Android (#21163)" (#21513)

This reverts commit 539034ae.
上级 40600024
...@@ -66,8 +66,7 @@ public class AndroidKeyProcessor { ...@@ -66,8 +66,7 @@ public class AndroidKeyProcessor {
@NonNull TextInputPlugin textInputPlugin) { @NonNull TextInputPlugin textInputPlugin) {
this.keyEventChannel = keyEventChannel; this.keyEventChannel = keyEventChannel;
this.textInputPlugin = textInputPlugin; this.textInputPlugin = textInputPlugin;
textInputPlugin.setKeyEventProcessor(this); this.eventResponder = new EventResponder(view);
this.eventResponder = new EventResponder(view, textInputPlugin);
this.keyEventChannel.setEventResponseHandler(eventResponder); this.keyEventChannel.setEventResponseHandler(eventResponder);
} }
...@@ -81,33 +80,53 @@ public class AndroidKeyProcessor { ...@@ -81,33 +80,53 @@ public class AndroidKeyProcessor {
} }
/** /**
* Called when a key event is received by the {@link FlutterView} or the {@link * Called when a key up event is received by the {@link FlutterView}.
* InputConnectionAdaptor}.
* *
* @param keyEvent the Android key event to respond to. * @param keyEvent the Android key event to respond to.
* @return true if the key event should not be propagated to other Android components. Delayed * @return true if the key event should not be propagated to other Android components. Delayed
* synthesis events will return false, so that other components may handle them. * synthesis events will return false, so that other components may handle them.
*/ */
public boolean onKeyEvent(@NonNull KeyEvent keyEvent) { public boolean onKeyUp(@NonNull KeyEvent keyEvent) {
int action = keyEvent.getAction(); if (eventResponder.dispatchingKeyEvent) {
if (action != KeyEvent.ACTION_DOWN && action != KeyEvent.ACTION_UP) { // Don't handle it if it is from our own delayed event synthesis.
// There is theoretically a KeyEvent.ACTION_MULTIPLE, but that shouldn't
// be sent anymore anyhow.
return false; return false;
} }
Character complexCharacter = applyCombiningCharacterToBaseCharacter(keyEvent.getUnicodeChar());
KeyEventChannel.FlutterKeyEvent flutterEvent =
new KeyEventChannel.FlutterKeyEvent(keyEvent, complexCharacter, eventIdSerial++);
keyEventChannel.keyUp(flutterEvent);
eventResponder.addEvent(flutterEvent.eventId, keyEvent);
return true;
}
/**
* Called when a key down event is received by the {@link FlutterView}.
*
* @param keyEvent the Android key event to respond to.
* @return true if the key event should not be propagated to other Android components. Delayed
* synthesis events will return false, so that other components may handle them.
*/
public boolean onKeyDown(@NonNull KeyEvent keyEvent) {
if (eventResponder.dispatchingKeyEvent) { if (eventResponder.dispatchingKeyEvent) {
// Don't handle it if it is from our own delayed event synthesis. // Don't handle it if it is from our own delayed event synthesis.
return false; return false;
} }
// If the textInputPlugin is still valid and accepting text, then we'll try
// and send the key event to it, assuming that if the event can be sent,
// that it has been handled.
if (textInputPlugin.getLastInputConnection() != null
&& textInputPlugin.getInputMethodManager().isAcceptingText()) {
if (textInputPlugin.getLastInputConnection().sendKeyEvent(keyEvent)) {
return true;
}
}
Character complexCharacter = applyCombiningCharacterToBaseCharacter(keyEvent.getUnicodeChar()); Character complexCharacter = applyCombiningCharacterToBaseCharacter(keyEvent.getUnicodeChar());
KeyEventChannel.FlutterKeyEvent flutterEvent = KeyEventChannel.FlutterKeyEvent flutterEvent =
new KeyEventChannel.FlutterKeyEvent(keyEvent, complexCharacter, eventIdSerial++); new KeyEventChannel.FlutterKeyEvent(keyEvent, complexCharacter, eventIdSerial++);
if (action == KeyEvent.ACTION_DOWN) { keyEventChannel.keyDown(flutterEvent);
keyEventChannel.keyDown(flutterEvent);
} else {
keyEventChannel.keyUp(flutterEvent);
}
eventResponder.addEvent(flutterEvent.eventId, keyEvent); eventResponder.addEvent(flutterEvent.eventId, keyEvent);
return true; return true;
} }
...@@ -177,12 +196,10 @@ public class AndroidKeyProcessor { ...@@ -177,12 +196,10 @@ public class AndroidKeyProcessor {
private static final long MAX_PENDING_EVENTS = 1000; private static final long MAX_PENDING_EVENTS = 1000;
final Deque<Entry<Long, KeyEvent>> pendingEvents = new ArrayDeque<Entry<Long, KeyEvent>>(); final Deque<Entry<Long, KeyEvent>> pendingEvents = new ArrayDeque<Entry<Long, KeyEvent>>();
@NonNull private final View view; @NonNull private final View view;
@NonNull private final TextInputPlugin textInputPlugin;
boolean dispatchingKeyEvent = false; boolean dispatchingKeyEvent = false;
public EventResponder(@NonNull View view, @NonNull TextInputPlugin textInputPlugin) { public EventResponder(@NonNull View view) {
this.view = view; this.view = view;
this.textInputPlugin = textInputPlugin;
} }
/** /**
...@@ -250,26 +267,12 @@ public class AndroidKeyProcessor { ...@@ -250,26 +267,12 @@ public class AndroidKeyProcessor {
* @param event the event to be dispatched to the activity. * @param event the event to be dispatched to the activity.
*/ */
public void dispatchKeyEvent(KeyEvent event) { public void dispatchKeyEvent(KeyEvent event) {
// If the textInputPlugin is still valid and accepting text, then we'll try
// and send the key event to it, assuming that if the event can be sent,
// that it has been handled.
if (textInputPlugin.getLastInputConnection() != null
&& textInputPlugin.getInputMethodManager().isAcceptingText()) {
dispatchingKeyEvent = true;
boolean handled = textInputPlugin.getLastInputConnection().sendKeyEvent(event);
dispatchingKeyEvent = false;
if (handled) {
return;
}
}
// Since the framework didn't handle it, dispatch the key again. // Since the framework didn't handle it, dispatch the key again.
if (view != null) { if (view != null) {
// Turn on dispatchingKeyEvent so that we don't dispatch to ourselves and // Turn on dispatchingKeyEvent so that we don't dispatch to ourselves and
// send it to the framework again. // send it to the framework again.
dispatchingKeyEvent = true; dispatchingKeyEvent = true;
view.getRootView().dispatchKeyEvent(event);
view.getRootView().dispatchKeyEventPreIme(event);
dispatchingKeyEvent = false; dispatchingKeyEvent = false;
} }
} }
......
...@@ -721,7 +721,27 @@ public class FlutterView extends FrameLayout implements MouseCursorPlugin.MouseC ...@@ -721,7 +721,27 @@ public class FlutterView extends FrameLayout implements MouseCursorPlugin.MouseC
} }
/** /**
* Invoked when a hardware key is pressed or released, before the IME receives the key. * Invoked when key is released.
*
* <p>This method is typically invoked in response to the release of a physical keyboard key or a
* D-pad button. It is generally not invoked when a virtual software keyboard is used, though a
* software keyboard may choose to invoke this method in some situations.
*
* <p>{@link KeyEvent}s are sent from Android to Flutter. {@link AndroidKeyProcessor} may do some
* additional work with the given {@link KeyEvent}, e.g., combine this {@code keyCode} with the
* previous {@code keyCode} to generate a unicode combined character.
*/
@Override
public boolean onKeyUp(int keyCode, @NonNull KeyEvent event) {
if (!isAttachedToFlutterEngine()) {
return super.onKeyUp(keyCode, event);
}
return androidKeyProcessor.onKeyUp(event) || super.onKeyUp(keyCode, event);
}
/**
* Invoked when key is pressed.
* *
* <p>This method is typically invoked in response to the press of a physical keyboard key or a * <p>This method is typically invoked in response to the press of a physical keyboard key or a
* D-pad button. It is generally not invoked when a virtual software keyboard is used, though a * D-pad button. It is generally not invoked when a virtual software keyboard is used, though a
...@@ -732,13 +752,12 @@ public class FlutterView extends FrameLayout implements MouseCursorPlugin.MouseC ...@@ -732,13 +752,12 @@ public class FlutterView extends FrameLayout implements MouseCursorPlugin.MouseC
* previous {@code keyCode} to generate a unicode combined character. * previous {@code keyCode} to generate a unicode combined character.
*/ */
@Override @Override
public boolean dispatchKeyEventPreIme(KeyEvent event) { public boolean onKeyDown(int keyCode, @NonNull KeyEvent event) {
// If the key processor doesn't handle it, then send it on to the if (!isAttachedToFlutterEngine()) {
// superclass. The key processor will typically handle all events except return super.onKeyDown(keyCode, event);
// those where it has re-dispatched the event after receiving a reply from }
// the framework that the framework did not handle it.
return (isAttachedToFlutterEngine() && androidKeyProcessor.onKeyEvent(event)) return androidKeyProcessor.onKeyDown(event) || super.onKeyDown(keyCode, event);
|| super.dispatchKeyEventPreIme(event);
} }
/** /**
......
...@@ -27,7 +27,6 @@ import android.view.inputmethod.ExtractedTextRequest; ...@@ -27,7 +27,6 @@ import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.InputMethodManager; import android.view.inputmethod.InputMethodManager;
import android.view.inputmethod.InputMethodSubtype; import android.view.inputmethod.InputMethodSubtype;
import io.flutter.Log; import io.flutter.Log;
import io.flutter.embedding.android.AndroidKeyProcessor;
import io.flutter.embedding.engine.FlutterJNI; import io.flutter.embedding.engine.FlutterJNI;
import io.flutter.embedding.engine.systemchannels.TextInputChannel; import io.flutter.embedding.engine.systemchannels.TextInputChannel;
...@@ -35,7 +34,6 @@ class InputConnectionAdaptor extends BaseInputConnection { ...@@ -35,7 +34,6 @@ class InputConnectionAdaptor extends BaseInputConnection {
private final View mFlutterView; private final View mFlutterView;
private final int mClient; private final int mClient;
private final TextInputChannel textInputChannel; private final TextInputChannel textInputChannel;
private final AndroidKeyProcessor keyProcessor;
private final Editable mEditable; private final Editable mEditable;
private final EditorInfo mEditorInfo; private final EditorInfo mEditorInfo;
private int mBatchCount; private int mBatchCount;
...@@ -99,7 +97,6 @@ class InputConnectionAdaptor extends BaseInputConnection { ...@@ -99,7 +97,6 @@ class InputConnectionAdaptor extends BaseInputConnection {
View view, View view,
int client, int client,
TextInputChannel textInputChannel, TextInputChannel textInputChannel,
AndroidKeyProcessor keyProcessor,
Editable editable, Editable editable,
EditorInfo editorInfo, EditorInfo editorInfo,
FlutterJNI flutterJNI) { FlutterJNI flutterJNI) {
...@@ -110,7 +107,6 @@ class InputConnectionAdaptor extends BaseInputConnection { ...@@ -110,7 +107,6 @@ class InputConnectionAdaptor extends BaseInputConnection {
mEditable = editable; mEditable = editable;
mEditorInfo = editorInfo; mEditorInfo = editorInfo;
mBatchCount = 0; mBatchCount = 0;
this.keyProcessor = keyProcessor;
this.flutterTextUtils = new FlutterTextUtils(flutterJNI); this.flutterTextUtils = new FlutterTextUtils(flutterJNI);
// We create a dummy Layout with max width so that the selection // We create a dummy Layout with max width so that the selection
// shifting acts as if all text were in one line. // shifting acts as if all text were in one line.
...@@ -132,10 +128,9 @@ class InputConnectionAdaptor extends BaseInputConnection { ...@@ -132,10 +128,9 @@ class InputConnectionAdaptor extends BaseInputConnection {
View view, View view,
int client, int client,
TextInputChannel textInputChannel, TextInputChannel textInputChannel,
AndroidKeyProcessor keyProcessor,
Editable editable, Editable editable,
EditorInfo editorInfo) { EditorInfo editorInfo) {
this(view, client, textInputChannel, keyProcessor, editable, editorInfo, new FlutterJNI()); this(view, client, textInputChannel, editable, editorInfo, new FlutterJNI());
} }
// Send the current state of the editable to Flutter. // Send the current state of the editable to Flutter.
...@@ -328,14 +323,6 @@ class InputConnectionAdaptor extends BaseInputConnection { ...@@ -328,14 +323,6 @@ class InputConnectionAdaptor extends BaseInputConnection {
@Override @Override
public boolean sendKeyEvent(KeyEvent event) { public boolean sendKeyEvent(KeyEvent event) {
// Give the key processor a chance to process this event. It will send it
// to the framework to be handled and return true. If the framework ends up
// not handling it, the processor will re-send the event, this time
// returning false so that it can be processed here.
if (keyProcessor != null && keyProcessor.onKeyEvent(event)) {
return true;
}
markDirty(); markDirty();
if (event.getAction() == KeyEvent.ACTION_DOWN) { if (event.getAction() == KeyEvent.ACTION_DOWN) {
if (event.getKeyCode() == KeyEvent.KEYCODE_DEL) { if (event.getKeyCode() == KeyEvent.KEYCODE_DEL) {
......
...@@ -33,7 +33,6 @@ import androidx.annotation.NonNull; ...@@ -33,7 +33,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi; import androidx.annotation.RequiresApi;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
import io.flutter.embedding.android.AndroidKeyProcessor;
import io.flutter.embedding.engine.systemchannels.TextInputChannel; import io.flutter.embedding.engine.systemchannels.TextInputChannel;
import io.flutter.plugin.platform.PlatformViewsController; import io.flutter.plugin.platform.PlatformViewsController;
import java.util.HashMap; import java.util.HashMap;
...@@ -55,7 +54,6 @@ public class TextInputPlugin { ...@@ -55,7 +54,6 @@ public class TextInputPlugin {
@Nullable private Rect lastClientRect; @Nullable private Rect lastClientRect;
private final boolean restartAlwaysRequired; private final boolean restartAlwaysRequired;
private ImeSyncDeferringInsetsCallback imeSyncCallback; private ImeSyncDeferringInsetsCallback imeSyncCallback;
private AndroidKeyProcessor keyProcessor;
// When true following calls to createInputConnection will return the cached lastInputConnection // When true following calls to createInputConnection will return the cached lastInputConnection
// if the input // if the input
...@@ -329,15 +327,6 @@ public class TextInputPlugin { ...@@ -329,15 +327,6 @@ public class TextInputPlugin {
return imeSyncCallback; return imeSyncCallback;
} }
@NonNull
public AndroidKeyProcessor getKeyEventProcessor() {
return keyProcessor;
}
public void setKeyEventProcessor(AndroidKeyProcessor processor) {
keyProcessor = processor;
}
/** /**
* Use the current platform view input connection until unlockPlatformViewInputConnection is * Use the current platform view input connection until unlockPlatformViewInputConnection is
* called. * called.
...@@ -480,8 +469,7 @@ public class TextInputPlugin { ...@@ -480,8 +469,7 @@ public class TextInputPlugin {
outAttrs.imeOptions |= enterAction; outAttrs.imeOptions |= enterAction;
InputConnectionAdaptor connection = InputConnectionAdaptor connection =
new InputConnectionAdaptor( new InputConnectionAdaptor(view, inputTarget.id, textInputChannel, mEditable, outAttrs);
view, inputTarget.id, textInputChannel, keyProcessor, mEditable, outAttrs);
outAttrs.initialSelStart = Selection.getSelectionStart(mEditable); outAttrs.initialSelStart = Selection.getSelectionStart(mEditable);
outAttrs.initialSelEnd = Selection.getSelectionEnd(mEditable); outAttrs.initialSelEnd = Selection.getSelectionEnd(mEditable);
......
...@@ -268,9 +268,19 @@ public class FlutterView extends SurfaceView ...@@ -268,9 +268,19 @@ public class FlutterView extends SurfaceView
} }
@Override @Override
public boolean dispatchKeyEventPreIme(KeyEvent event) { public boolean onKeyUp(int keyCode, KeyEvent event) {
return (isAttached() && androidKeyProcessor.onKeyEvent(event)) if (!isAttached()) {
|| super.dispatchKeyEventPreIme(event); return super.onKeyUp(keyCode, event);
}
return androidKeyProcessor.onKeyUp(event) || super.onKeyUp(keyCode, event);
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (!isAttached()) {
return super.onKeyDown(keyCode, event);
}
return androidKeyProcessor.onKeyDown(event) || super.onKeyDown(keyCode, event);
} }
public FlutterNativeView getFlutterNativeView() { public FlutterNativeView getFlutterNativeView() {
......
...@@ -51,11 +51,11 @@ public class AndroidKeyProcessorTest { ...@@ -51,11 +51,11 @@ public class AndroidKeyProcessorTest {
AndroidKeyProcessor processor = AndroidKeyProcessor processor =
new AndroidKeyProcessor(fakeView, fakeKeyEventChannel, mock(TextInputPlugin.class)); new AndroidKeyProcessor(fakeView, fakeKeyEventChannel, mock(TextInputPlugin.class));
boolean result = processor.onKeyEvent(new FakeKeyEvent(KeyEvent.ACTION_DOWN, 65)); boolean result = processor.onKeyDown(new FakeKeyEvent(KeyEvent.ACTION_DOWN, 65));
assertEquals(true, result); assertEquals(true, result);
verify(fakeKeyEventChannel, times(1)).keyDown(any(KeyEventChannel.FlutterKeyEvent.class)); verify(fakeKeyEventChannel, times(1)).keyDown(any(KeyEventChannel.FlutterKeyEvent.class));
verify(fakeKeyEventChannel, times(0)).keyUp(any(KeyEventChannel.FlutterKeyEvent.class)); verify(fakeKeyEventChannel, times(0)).keyUp(any(KeyEventChannel.FlutterKeyEvent.class));
verify(fakeView, times(0)).dispatchKeyEventPreIme(any(KeyEvent.class)); verify(fakeView, times(0)).dispatchKeyEvent(any(KeyEvent.class));
} }
@Test @Test
...@@ -97,31 +97,31 @@ public class AndroidKeyProcessorTest { ...@@ -97,31 +97,31 @@ public class AndroidKeyProcessorTest {
ArgumentCaptor.forClass(KeyEventChannel.FlutterKeyEvent.class); ArgumentCaptor.forClass(KeyEventChannel.FlutterKeyEvent.class);
FakeKeyEvent fakeKeyEvent = new FakeKeyEvent(KeyEvent.ACTION_DOWN, 65); FakeKeyEvent fakeKeyEvent = new FakeKeyEvent(KeyEvent.ACTION_DOWN, 65);
boolean result = processor.onKeyEvent(fakeKeyEvent); boolean result = processor.onKeyDown(fakeKeyEvent);
assertEquals(true, result); assertEquals(true, result);
// Capture the FlutterKeyEvent so we can find out its event ID to use when // Capture the FlutterKeyEvent so we can find out its event ID to use when
// faking our response. // faking our response.
verify(fakeKeyEventChannel, times(1)).keyDown(eventCaptor.capture()); verify(fakeKeyEventChannel, times(1)).keyDown(eventCaptor.capture());
boolean[] dispatchResult = {true}; boolean[] dispatchResult = {true};
when(fakeView.dispatchKeyEventPreIme(any(KeyEvent.class))) when(fakeView.dispatchKeyEvent(any(KeyEvent.class)))
.then( .then(
new Answer<Boolean>() { new Answer<Boolean>() {
@Override @Override
public Boolean answer(InvocationOnMock invocation) throws Throwable { public Boolean answer(InvocationOnMock invocation) throws Throwable {
KeyEvent event = (KeyEvent) invocation.getArguments()[0]; KeyEvent event = (KeyEvent) invocation.getArguments()[0];
assertEquals(fakeKeyEvent, event); assertEquals(fakeKeyEvent, event);
dispatchResult[0] = processor.onKeyEvent(event); dispatchResult[0] = processor.onKeyDown(event);
return dispatchResult[0]; return dispatchResult[0];
} }
}); });
// Fake a response from the framework. // Fake a response from the framework.
handlerCaptor.getValue().onKeyEventNotHandled(eventCaptor.getValue().eventId); handlerCaptor.getValue().onKeyEventNotHandled(eventCaptor.getValue().eventId);
verify(fakeView, times(1)).dispatchKeyEventPreIme(fakeKeyEvent); verify(fakeView, times(1)).dispatchKeyEvent(fakeKeyEvent);
assertEquals(false, dispatchResult[0]); assertEquals(false, dispatchResult[0]);
verify(fakeKeyEventChannel, times(0)).keyUp(any(KeyEventChannel.FlutterKeyEvent.class)); verify(fakeKeyEventChannel, times(0)).keyUp(any(KeyEventChannel.FlutterKeyEvent.class));
verify(fakeRootView, times(1)).dispatchKeyEventPreIme(fakeKeyEvent); verify(fakeRootView, times(1)).dispatchKeyEvent(fakeKeyEvent);
} }
public void synthesizesEventsWhenKeyUpNotHandled() { public void synthesizesEventsWhenKeyUpNotHandled() {
...@@ -147,31 +147,31 @@ public class AndroidKeyProcessorTest { ...@@ -147,31 +147,31 @@ public class AndroidKeyProcessorTest {
ArgumentCaptor.forClass(KeyEventChannel.FlutterKeyEvent.class); ArgumentCaptor.forClass(KeyEventChannel.FlutterKeyEvent.class);
FakeKeyEvent fakeKeyEvent = new FakeKeyEvent(KeyEvent.ACTION_UP, 65); FakeKeyEvent fakeKeyEvent = new FakeKeyEvent(KeyEvent.ACTION_UP, 65);
boolean result = processor.onKeyEvent(fakeKeyEvent); boolean result = processor.onKeyUp(fakeKeyEvent);
assertEquals(true, result); assertEquals(true, result);
// Capture the FlutterKeyEvent so we can find out its event ID to use when // Capture the FlutterKeyEvent so we can find out its event ID to use when
// faking our response. // faking our response.
verify(fakeKeyEventChannel, times(1)).keyUp(eventCaptor.capture()); verify(fakeKeyEventChannel, times(1)).keyUp(eventCaptor.capture());
boolean[] dispatchResult = {true}; boolean[] dispatchResult = {true};
when(fakeView.dispatchKeyEventPreIme(any(KeyEvent.class))) when(fakeView.dispatchKeyEvent(any(KeyEvent.class)))
.then( .then(
new Answer<Boolean>() { new Answer<Boolean>() {
@Override @Override
public Boolean answer(InvocationOnMock invocation) throws Throwable { public Boolean answer(InvocationOnMock invocation) throws Throwable {
KeyEvent event = (KeyEvent) invocation.getArguments()[0]; KeyEvent event = (KeyEvent) invocation.getArguments()[0];
assertEquals(fakeKeyEvent, event); assertEquals(fakeKeyEvent, event);
dispatchResult[0] = processor.onKeyEvent(event); dispatchResult[0] = processor.onKeyUp(event);
return dispatchResult[0]; return dispatchResult[0];
} }
}); });
// Fake a response from the framework. // Fake a response from the framework.
handlerCaptor.getValue().onKeyEventNotHandled(eventCaptor.getValue().eventId); handlerCaptor.getValue().onKeyEventNotHandled(eventCaptor.getValue().eventId);
verify(fakeView, times(1)).dispatchKeyEventPreIme(fakeKeyEvent); verify(fakeView, times(1)).dispatchKeyEvent(fakeKeyEvent);
assertEquals(false, dispatchResult[0]); assertEquals(false, dispatchResult[0]);
verify(fakeKeyEventChannel, times(0)).keyUp(any(KeyEventChannel.FlutterKeyEvent.class)); verify(fakeKeyEventChannel, times(0)).keyUp(any(KeyEventChannel.FlutterKeyEvent.class));
verify(fakeRootView, times(1)).dispatchKeyEventPreIme(fakeKeyEvent); verify(fakeRootView, times(1)).dispatchKeyEvent(fakeKeyEvent);
} }
@NonNull @NonNull
......
...@@ -25,7 +25,6 @@ import android.view.KeyEvent; ...@@ -25,7 +25,6 @@ import android.view.KeyEvent;
import android.view.View; import android.view.View;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.ExtractedText; import android.view.inputmethod.ExtractedText;
import io.flutter.embedding.android.AndroidKeyProcessor;
import io.flutter.embedding.engine.FlutterJNI; import io.flutter.embedding.engine.FlutterJNI;
import io.flutter.embedding.engine.dart.DartExecutor; import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.embedding.engine.systemchannels.TextInputChannel; import io.flutter.embedding.engine.systemchannels.TextInputChannel;
...@@ -69,7 +68,6 @@ public class InputConnectionAdaptorTest { ...@@ -69,7 +68,6 @@ public class InputConnectionAdaptorTest {
DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJni, mock(AssetManager.class))); DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJni, mock(AssetManager.class)));
int inputTargetId = 0; int inputTargetId = 0;
TextInputChannel textInputChannel = new TextInputChannel(dartExecutor); TextInputChannel textInputChannel = new TextInputChannel(dartExecutor);
AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class);
Editable mEditable = Editable.Factory.getInstance().newEditable(""); Editable mEditable = Editable.Factory.getInstance().newEditable("");
Editable spyEditable = spy(mEditable); Editable spyEditable = spy(mEditable);
EditorInfo outAttrs = new EditorInfo(); EditorInfo outAttrs = new EditorInfo();
...@@ -77,7 +75,7 @@ public class InputConnectionAdaptorTest { ...@@ -77,7 +75,7 @@ public class InputConnectionAdaptorTest {
InputConnectionAdaptor inputConnectionAdaptor = InputConnectionAdaptor inputConnectionAdaptor =
new InputConnectionAdaptor( new InputConnectionAdaptor(
testView, inputTargetId, textInputChannel, mockKeyProcessor, spyEditable, outAttrs); testView, inputTargetId, textInputChannel, spyEditable, outAttrs);
// Send an enter key and make sure the Editable received it. // Send an enter key and make sure the Editable received it.
FakeKeyEvent keyEvent = new FakeKeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER); FakeKeyEvent keyEvent = new FakeKeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_ENTER);
...@@ -158,11 +156,10 @@ public class InputConnectionAdaptorTest { ...@@ -158,11 +156,10 @@ public class InputConnectionAdaptorTest {
FlutterJNI mockFlutterJNI = mock(FlutterJNI.class); FlutterJNI mockFlutterJNI = mock(FlutterJNI.class);
DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class))); DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class)));
TextInputChannel textInputChannel = new TextInputChannel(dartExecutor); TextInputChannel textInputChannel = new TextInputChannel(dartExecutor);
AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class);
Editable editable = sampleEditable(0, 0); Editable editable = sampleEditable(0, 0);
InputConnectionAdaptor adaptor = InputConnectionAdaptor adaptor =
new InputConnectionAdaptor( new InputConnectionAdaptor(
testView, client, textInputChannel, mockKeyProcessor, editable, null, mockFlutterJNI); testView, client, textInputChannel, editable, null, mockFlutterJNI);
adaptor.performPrivateCommand("actionCommand", null); adaptor.performPrivateCommand("actionCommand", null);
ArgumentCaptor<String> channelCaptor = ArgumentCaptor.forClass(String.class); ArgumentCaptor<String> channelCaptor = ArgumentCaptor.forClass(String.class);
...@@ -186,11 +183,10 @@ public class InputConnectionAdaptorTest { ...@@ -186,11 +183,10 @@ public class InputConnectionAdaptorTest {
FlutterJNI mockFlutterJNI = mock(FlutterJNI.class); FlutterJNI mockFlutterJNI = mock(FlutterJNI.class);
DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class))); DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class)));
TextInputChannel textInputChannel = new TextInputChannel(dartExecutor); TextInputChannel textInputChannel = new TextInputChannel(dartExecutor);
AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class);
Editable editable = sampleEditable(0, 0); Editable editable = sampleEditable(0, 0);
InputConnectionAdaptor adaptor = InputConnectionAdaptor adaptor =
new InputConnectionAdaptor( new InputConnectionAdaptor(
testView, client, textInputChannel, mockKeyProcessor, editable, null, mockFlutterJNI); testView, client, textInputChannel, editable, null, mockFlutterJNI);
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
byte[] buffer = new byte[] {'a', 'b', 'c', 'd'}; byte[] buffer = new byte[] {'a', 'b', 'c', 'd'};
...@@ -220,11 +216,10 @@ public class InputConnectionAdaptorTest { ...@@ -220,11 +216,10 @@ public class InputConnectionAdaptorTest {
FlutterJNI mockFlutterJNI = mock(FlutterJNI.class); FlutterJNI mockFlutterJNI = mock(FlutterJNI.class);
DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class))); DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class)));
TextInputChannel textInputChannel = new TextInputChannel(dartExecutor); TextInputChannel textInputChannel = new TextInputChannel(dartExecutor);
AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class);
Editable editable = sampleEditable(0, 0); Editable editable = sampleEditable(0, 0);
InputConnectionAdaptor adaptor = InputConnectionAdaptor adaptor =
new InputConnectionAdaptor( new InputConnectionAdaptor(
testView, client, textInputChannel, mockKeyProcessor, editable, null, mockFlutterJNI); testView, client, textInputChannel, editable, null, mockFlutterJNI);
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
byte b = 3; byte b = 3;
...@@ -252,11 +247,10 @@ public class InputConnectionAdaptorTest { ...@@ -252,11 +247,10 @@ public class InputConnectionAdaptorTest {
FlutterJNI mockFlutterJNI = mock(FlutterJNI.class); FlutterJNI mockFlutterJNI = mock(FlutterJNI.class);
DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class))); DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class)));
TextInputChannel textInputChannel = new TextInputChannel(dartExecutor); TextInputChannel textInputChannel = new TextInputChannel(dartExecutor);
AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class);
Editable editable = sampleEditable(0, 0); Editable editable = sampleEditable(0, 0);
InputConnectionAdaptor adaptor = InputConnectionAdaptor adaptor =
new InputConnectionAdaptor( new InputConnectionAdaptor(
testView, client, textInputChannel, mockKeyProcessor, editable, null, mockFlutterJNI); testView, client, textInputChannel, editable, null, mockFlutterJNI);
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
char[] buffer = new char[] {'a', 'b', 'c', 'd'}; char[] buffer = new char[] {'a', 'b', 'c', 'd'};
...@@ -287,11 +281,10 @@ public class InputConnectionAdaptorTest { ...@@ -287,11 +281,10 @@ public class InputConnectionAdaptorTest {
FlutterJNI mockFlutterJNI = mock(FlutterJNI.class); FlutterJNI mockFlutterJNI = mock(FlutterJNI.class);
DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class))); DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class)));
TextInputChannel textInputChannel = new TextInputChannel(dartExecutor); TextInputChannel textInputChannel = new TextInputChannel(dartExecutor);
AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class);
Editable editable = sampleEditable(0, 0); Editable editable = sampleEditable(0, 0);
InputConnectionAdaptor adaptor = InputConnectionAdaptor adaptor =
new InputConnectionAdaptor( new InputConnectionAdaptor(
testView, client, textInputChannel, mockKeyProcessor, editable, null, mockFlutterJNI); testView, client, textInputChannel, editable, null, mockFlutterJNI);
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
char b = 'a'; char b = 'a';
...@@ -319,11 +312,10 @@ public class InputConnectionAdaptorTest { ...@@ -319,11 +312,10 @@ public class InputConnectionAdaptorTest {
FlutterJNI mockFlutterJNI = mock(FlutterJNI.class); FlutterJNI mockFlutterJNI = mock(FlutterJNI.class);
DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class))); DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class)));
TextInputChannel textInputChannel = new TextInputChannel(dartExecutor); TextInputChannel textInputChannel = new TextInputChannel(dartExecutor);
AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class);
Editable editable = sampleEditable(0, 0); Editable editable = sampleEditable(0, 0);
InputConnectionAdaptor adaptor = InputConnectionAdaptor adaptor =
new InputConnectionAdaptor( new InputConnectionAdaptor(
testView, client, textInputChannel, mockKeyProcessor, editable, null, mockFlutterJNI); testView, client, textInputChannel, editable, null, mockFlutterJNI);
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
CharSequence charSequence1 = new StringBuffer("abc"); CharSequence charSequence1 = new StringBuffer("abc");
...@@ -355,11 +347,10 @@ public class InputConnectionAdaptorTest { ...@@ -355,11 +347,10 @@ public class InputConnectionAdaptorTest {
FlutterJNI mockFlutterJNI = mock(FlutterJNI.class); FlutterJNI mockFlutterJNI = mock(FlutterJNI.class);
DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class))); DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class)));
TextInputChannel textInputChannel = new TextInputChannel(dartExecutor); TextInputChannel textInputChannel = new TextInputChannel(dartExecutor);
AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class);
Editable editable = sampleEditable(0, 0); Editable editable = sampleEditable(0, 0);
InputConnectionAdaptor adaptor = InputConnectionAdaptor adaptor =
new InputConnectionAdaptor( new InputConnectionAdaptor(
testView, client, textInputChannel, mockKeyProcessor, editable, null, mockFlutterJNI); testView, client, textInputChannel, editable, null, mockFlutterJNI);
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
CharSequence charSequence = new StringBuffer("abc"); CharSequence charSequence = new StringBuffer("abc");
...@@ -389,11 +380,10 @@ public class InputConnectionAdaptorTest { ...@@ -389,11 +380,10 @@ public class InputConnectionAdaptorTest {
FlutterJNI mockFlutterJNI = mock(FlutterJNI.class); FlutterJNI mockFlutterJNI = mock(FlutterJNI.class);
DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class))); DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class)));
TextInputChannel textInputChannel = new TextInputChannel(dartExecutor); TextInputChannel textInputChannel = new TextInputChannel(dartExecutor);
AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class);
Editable editable = sampleEditable(0, 0); Editable editable = sampleEditable(0, 0);
InputConnectionAdaptor adaptor = InputConnectionAdaptor adaptor =
new InputConnectionAdaptor( new InputConnectionAdaptor(
testView, client, textInputChannel, mockKeyProcessor, editable, null, mockFlutterJNI); testView, client, textInputChannel, editable, null, mockFlutterJNI);
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
float value = 0.5f; float value = 0.5f;
...@@ -421,11 +411,10 @@ public class InputConnectionAdaptorTest { ...@@ -421,11 +411,10 @@ public class InputConnectionAdaptorTest {
FlutterJNI mockFlutterJNI = mock(FlutterJNI.class); FlutterJNI mockFlutterJNI = mock(FlutterJNI.class);
DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class))); DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJNI, mock(AssetManager.class)));
TextInputChannel textInputChannel = new TextInputChannel(dartExecutor); TextInputChannel textInputChannel = new TextInputChannel(dartExecutor);
AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class);
Editable editable = sampleEditable(0, 0); Editable editable = sampleEditable(0, 0);
InputConnectionAdaptor adaptor = InputConnectionAdaptor adaptor =
new InputConnectionAdaptor( new InputConnectionAdaptor(
testView, client, textInputChannel, mockKeyProcessor, editable, null, mockFlutterJNI); testView, client, textInputChannel, editable, null, mockFlutterJNI);
Bundle bundle = new Bundle(); Bundle bundle = new Bundle();
float[] value = {0.5f, 0.6f}; float[] value = {0.5f, 0.6f};
...@@ -918,7 +907,6 @@ public class InputConnectionAdaptorTest { ...@@ -918,7 +907,6 @@ public class InputConnectionAdaptorTest {
DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJni, mock(AssetManager.class))); DartExecutor dartExecutor = spy(new DartExecutor(mockFlutterJni, mock(AssetManager.class)));
int inputTargetId = 0; int inputTargetId = 0;
TestTextInputChannel textInputChannel = new TestTextInputChannel(dartExecutor); TestTextInputChannel textInputChannel = new TestTextInputChannel(dartExecutor);
AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class);
Editable mEditable = Editable.Factory.getInstance().newEditable(""); Editable mEditable = Editable.Factory.getInstance().newEditable("");
Editable spyEditable = spy(mEditable); Editable spyEditable = spy(mEditable);
EditorInfo outAttrs = new EditorInfo(); EditorInfo outAttrs = new EditorInfo();
...@@ -926,7 +914,7 @@ public class InputConnectionAdaptorTest { ...@@ -926,7 +914,7 @@ public class InputConnectionAdaptorTest {
InputConnectionAdaptor inputConnectionAdaptor = InputConnectionAdaptor inputConnectionAdaptor =
new InputConnectionAdaptor( new InputConnectionAdaptor(
testView, inputTargetId, textInputChannel, mockKeyProcessor, spyEditable, outAttrs); testView, inputTargetId, textInputChannel, spyEditable, outAttrs);
inputConnectionAdaptor.beginBatchEdit(); inputConnectionAdaptor.beginBatchEdit();
assertEquals(textInputChannel.updateEditingStateInvocations, 0); assertEquals(textInputChannel.updateEditingStateInvocations, 0);
...@@ -1171,7 +1159,6 @@ public class InputConnectionAdaptorTest { ...@@ -1171,7 +1159,6 @@ public class InputConnectionAdaptorTest {
int client = 0; int client = 0;
TextInputChannel textInputChannel = mock(TextInputChannel.class); TextInputChannel textInputChannel = mock(TextInputChannel.class);
FlutterJNI mockFlutterJNI = mock(FlutterJNI.class); FlutterJNI mockFlutterJNI = mock(FlutterJNI.class);
AndroidKeyProcessor mockKeyProcessor = mock(AndroidKeyProcessor.class);
when(mockFlutterJNI.nativeFlutterTextUtilsIsEmoji(anyInt())) when(mockFlutterJNI.nativeFlutterTextUtilsIsEmoji(anyInt()))
.thenAnswer((invocation) -> Emoji.isEmoji((int) invocation.getArguments()[0])); .thenAnswer((invocation) -> Emoji.isEmoji((int) invocation.getArguments()[0]));
when(mockFlutterJNI.nativeFlutterTextUtilsIsEmojiModifier(anyInt())) when(mockFlutterJNI.nativeFlutterTextUtilsIsEmojiModifier(anyInt()))
...@@ -1188,7 +1175,7 @@ public class InputConnectionAdaptorTest { ...@@ -1188,7 +1175,7 @@ public class InputConnectionAdaptorTest {
.thenAnswer( .thenAnswer(
(invocation) -> Emoji.isRegionalIndicatorSymbol((int) invocation.getArguments()[0])); (invocation) -> Emoji.isRegionalIndicatorSymbol((int) invocation.getArguments()[0]));
return new InputConnectionAdaptor( return new InputConnectionAdaptor(
testView, client, textInputChannel, mockKeyProcessor, editable, null, mockFlutterJNI); testView, client, textInputChannel, editable, null, mockFlutterJNI);
} }
private class TestTextInputChannel extends TextInputChannel { private class TestTextInputChannel extends TextInputChannel {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册