Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Revert "Keyboard support for embedded Android views." #9239

Merged
merged 1 commit into from
Jun 8, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -477,8 +477,7 @@ public void attachToFlutterEngine(@NonNull FlutterEngine flutterEngine) {
// in a way that Flutter understands.
textInputPlugin = new TextInputPlugin(
this,
this.flutterEngine.getDartExecutor(),
null
this.flutterEngine.getDartExecutor()
);
androidKeyProcessor = new AndroidKeyProcessor(
this.flutterEngine.getKeyEventChannel(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,6 @@ public class PlatformViewsChannel {
private final MethodChannel channel;
private PlatformViewsHandler handler;

public void invokeViewFocused(int viewId) {
if (channel == null) {
return;
}
channel.invokeMethod("viewFocused", viewId);
}

private final MethodChannel.MethodCallHandler parsingHandler = new MethodChannel.MethodCallHandler() {
@Override
public void onMethodCall(MethodCall call, MethodChannel.Result result) {
Expand All @@ -58,9 +51,6 @@ public void onMethodCall(MethodCall call, MethodChannel.Result result) {
case "setDirection":
setDirection(call, result);
break;
case "clearFocus":
clearFocus(call, result);
break;
default:
result.notImplemented();
}
Expand Down Expand Up @@ -182,20 +172,6 @@ private void setDirection(@NonNull MethodCall call, @NonNull MethodChannel.Resul
);
}
}

private void clearFocus(MethodCall call, MethodChannel.Result result) {
int viewId = call.arguments();
try {
handler.clearFocus(viewId);
result.success(null);
} catch (IllegalStateException exception) {
result.error(
"error",
exception.getMessage(),
null
);
}
}
};

/**
Expand Down Expand Up @@ -265,11 +241,6 @@ void resizePlatformView(
*/
// TODO(mattcarroll): Introduce an annotation for @TextureId
void setDirection(int viewId, int direction);

/**
* Clears the focus from the platform view with a give id if it is currently focused.
*/
void clearFocus(int viewId);
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,6 @@ public void onMethodCall(MethodCall call, MethodChannel.Result result) {
result.error("error", exception.getMessage(), null);
}
break;
case "TextInput.setPlatformViewClient":
final int id = (int) args;
textInputMethodHandler.setPlatformViewClient(id);
break;
case "TextInput.setEditingState":
try {
final JSONObject editingState = (JSONObject) args;
Expand Down Expand Up @@ -222,16 +218,6 @@ public interface TextInputMethodHandler {
// TODO(mattcarroll): javadoc
void setClient(int textInputClientId, @NonNull Configuration configuration);

/**
* Sets a platform view as the text input client.
*
* Subsequent calls to createInputConnection will be delegated to the platform view until a
* different client is set.
*
* @param id the ID of the platform view to be set as a text input client.
*/
void setPlatformViewClient(int id);

// TODO(mattcarroll): javadoc
void setEditingState(@NonNull TextEditState editingState);

Expand Down
120 changes: 8 additions & 112 deletions shell/platform/android/io/flutter/plugin/editing/TextInputPlugin.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@

import io.flutter.embedding.engine.dart.DartExecutor;
import io.flutter.embedding.engine.systemchannels.TextInputChannel;
import io.flutter.plugin.platform.PlatformViewsController;
import io.flutter.view.FlutterView;

/**
* Android implementation of the text input plugin.
Expand All @@ -30,8 +30,7 @@ public class TextInputPlugin {
private final InputMethodManager mImm;
@NonNull
private final TextInputChannel textInputChannel;
@NonNull
private InputTarget inputTarget = new InputTarget(InputTarget.Type.NO_TARGET, 0);
private int mClient = 0;
@Nullable
private TextInputChannel.Configuration configuration;
@Nullable
Expand All @@ -40,13 +39,7 @@ public class TextInputPlugin {
@Nullable
private InputConnection lastInputConnection;

private PlatformViewsController platformViewsController;

// When true following calls to createInputConnection will return the cached lastInputConnection if the input
// target is a platform view. See the comments on lockPlatformViewInputConnection for more details.
private boolean isInputConnectionLocked;

public TextInputPlugin(View view, @NonNull DartExecutor dartExecutor, PlatformViewsController platformViewsController) {
public TextInputPlugin(View view, @NonNull DartExecutor dartExecutor) {
mView = view;
mImm = (InputMethodManager) view.getContext().getSystemService(
Context.INPUT_METHOD_SERVICE);
Expand All @@ -68,11 +61,6 @@ public void setClient(int textInputClientId, TextInputChannel.Configuration conf
setTextInputClient(textInputClientId, configuration);
}

@Override
public void setPlatformViewClient(int platformViewId) {
setPlatformViewTextInputClient(platformViewId);
}

@Override
public void setEditingState(TextInputChannel.TextEditState editingState) {
setTextInputEditingState(mView, editingState);
Expand All @@ -83,49 +71,13 @@ public void clearClient() {
clearTextInputClient();
}
});
this.platformViewsController = platformViewsController;
platformViewsController.attachTextInputPlugin(this);
}

@NonNull
public InputMethodManager getInputMethodManager() {
return mImm;
}

/***
* Use the current platform view input connection until unlockPlatformViewInputConnection is called.
*
* The current input connection instance is cached and any following call to @{link createInputConnection} returns
* the cached connection until unlockPlatformViewInputConnection is called.
*
* This is a no-op if the current input target isn't a platform view.
*
* This is used to preserve an input connection when moving a platform view from one virtual display to another.
*/
public void lockPlatformViewInputConnection() {
if (inputTarget.type == InputTarget.Type.PLATFORM_VIEW) {
isInputConnectionLocked = true;
}
}

/**
* Unlocks the input connection.
*
* See also: @{link lockPlatformViewInputConnection}.
*/
public void unlockPlatformViewInputConnection() {
isInputConnectionLocked = false;
}

/**
* Detaches the text input plugin from the platform views controller.
*
* The TextInputPlugin instance should not be used after calling this.
*/
public void destroy() {
platformViewsController.detachTextInputPlugin();
}

private static int inputTypeFromTextInputType(
TextInputChannel.InputType type,
boolean obscureText,
Expand Down Expand Up @@ -176,16 +128,8 @@ private static int inputTypeFromTextInputType(
}

public InputConnection createInputConnection(View view, EditorInfo outAttrs) {
if (inputTarget.type == InputTarget.Type.NO_TARGET) {
if (mClient == 0) {
lastInputConnection = null;
return null;
}

if (inputTarget.type == InputTarget.Type.PLATFORM_VIEW) {
if (isInputConnectionLocked) {
return lastInputConnection;
}
lastInputConnection = platformViewsController.getPlatformViewById(inputTarget.id).onCreateInputConnection(outAttrs);
return lastInputConnection;
}

Expand Down Expand Up @@ -214,7 +158,7 @@ public InputConnection createInputConnection(View view, EditorInfo outAttrs) {

InputConnectionAdaptor connection = new InputConnectionAdaptor(
view,
inputTarget.id,
mClient,
textInputChannel,
mEditable
);
Expand All @@ -236,26 +180,17 @@ private void showTextInput(View view) {
}

private void hideTextInput(View view) {
if (inputTarget.type == InputTarget.Type.FRAMEWORK_CLIENT) {
mImm.hideSoftInputFromWindow(view.getApplicationWindowToken(), 0);
}
mImm.hideSoftInputFromWindow(view.getApplicationWindowToken(), 0);
}

private void setTextInputClient(int client, TextInputChannel.Configuration configuration) {
inputTarget = new InputTarget(InputTarget.Type.FRAMEWORK_CLIENT, client);
mClient = client;
this.configuration = configuration;
mEditable = Editable.Factory.getInstance().newEditable("");

// setTextInputClient will be followed by a call to setTextInputEditingState.
// Do a restartInput at that time.
mRestartInputPending = true;
unlockPlatformViewInputConnection();
}

private void setPlatformViewTextInputClient(int platformViewId) {
inputTarget = new InputTarget(InputTarget.Type.PLATFORM_VIEW, platformViewId);
mImm.restartInput(mView);
mRestartInputPending = false;
}

private void applyStateToSelection(TextInputChannel.TextEditState state) {
Expand Down Expand Up @@ -285,45 +220,6 @@ private void setTextInputEditingState(View view, TextInputChannel.TextEditState
}

private void clearTextInputClient() {
if (inputTarget.type == InputTarget.Type.PLATFORM_VIEW) {
// Focus changes in the framework tree have no guarantees on the order focus nodes are notified. A node
// that lost focus may be notified before or after a node that gained focus.
// When moving the focus from a Flutter text field to an AndroidView, it is possible that the Flutter text
// field's focus node will be notified that it lost focus after the AndroidView was notified that it gained
// focus. When this happens the text field will send a clearTextInput command which we ignore.
// By doing this we prevent the framework from clearing a platform view input client(the only way to do so
// is to set a new framework text client). I don't see an obvious use case for "clearing" a platform views
// text input client, and it may be error prone as we don't know how the platform view manages the input
// connection and we probably shouldn't interfere.
// If we ever want to allow the framework to clear a platform view text client we should probably consider
// changing the focus manager such that focus nodes that lost focus are notified before focus nodes that
// gained focus as part of the same focus event.
return;
}
inputTarget = new InputTarget(InputTarget.Type.NO_TARGET, 0);
unlockPlatformViewInputConnection();
}

static private class InputTarget {
enum Type {
NO_TARGET,
// InputConnection is managed by the TextInputPlugin, and events are forwarded to the Flutter framework.
FRAMEWORK_CLIENT,
// InputConnection is managed by an embedded platform view.
PLATFORM_VIEW
}

public InputTarget(@NonNull Type type, int id) {
this.type = type;
this.id = id;
}

@NonNull
Type type;
// The ID of the input target.
//
// For framework clients this is the framework input connection client ID.
// For platform views this is the platform view's ID.
int id;
mClient = 0;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
* Facilitates interaction between the accessibility bridge and embedded platform views.
*/
public interface PlatformViewsAccessibilityDelegate {

/**
* Returns the root of the view hierarchy for the platform view with the requested id, or null if there is no
* corresponding view.
Expand Down
Loading