Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
revert last pieces
  • Loading branch information
Emmanuel Garcia committed Jun 21, 2022
commit 42adbc45774233b1607d99a3f8157d7667842ab3
Original file line number Diff line number Diff line change
Expand Up @@ -873,6 +873,21 @@ public InputConnection onCreateInputConnection(@NonNull EditorInfo outAttrs) {
return textInputPlugin.createInputConnection(this, keyboardManager, outAttrs);
}

/**
* Allows a {@code View} that is not currently the input connection target to invoke commands on
* the {@link android.view.inputmethod.InputMethodManager}, which is otherwise disallowed.
*
* <p>Returns true to allow non-input-connection-targets to invoke methods on {@code
* InputMethodManager}, or false to exclusively allow the input connection target to invoke such
* methods.
*/
@Override
public boolean checkInputConnectionProxy(View view) {
return flutterEngine != null
? flutterEngine.getPlatformViewsController().checkInputConnectionProxy(view)
: super.checkInputConnectionProxy(view);
}

/**
* Invoked when a hardware key is pressed or released.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,9 @@ public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result
try {
final JSONObject arguments = (JSONObject) args;
final int platformViewId = arguments.getInt("platformViewId");
textInputMethodHandler.setPlatformViewClient(platformViewId);
final boolean usesVirtualDisplay =
arguments.optBoolean("usesVirtualDisplay", false);
textInputMethodHandler.setPlatformViewClient(platformViewId, usesVirtualDisplay);
result.success(null);
} catch (JSONException exception) {
result.error("error", exception.getMessage(), null);
Expand Down Expand Up @@ -401,8 +403,10 @@ public interface TextInputMethodHandler {
* different client is set.
*
* @param id the ID of the platform view to be set as a text input client.
* @param usesVirtualDisplay True if the platform view uses a virtual display, false if it uses
* hybrid composition.
*/
void setPlatformViewClient(int id);
void setPlatformViewClient(int id, boolean usesVirtualDisplay);

/**
* Sets the size and the transform matrix of the current text input client.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,7 @@ public void show() {

@Override
public void hide() {
if (inputTarget.type == InputTarget.Type.PLATFORM_VIEW) {
if (inputTarget.type == InputTarget.Type.HC_PLATFORM_VIEW) {
notifyViewExited();
} else {
hideTextInput(mView);
Expand Down Expand Up @@ -136,8 +136,8 @@ public void setClient(
}

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

@Override
Expand Down Expand Up @@ -196,7 +196,7 @@ ImeSyncDeferringInsetsCallback getImeSyncCallback() {
* display to another.
*/
public void lockPlatformViewInputConnection() {
if (inputTarget.type == InputTarget.Type.PLATFORM_VIEW) {
if (inputTarget.type == InputTarget.Type.VD_PLATFORM_VIEW) {
isInputConnectionLocked = true;
}
}
Expand All @@ -207,7 +207,9 @@ public void lockPlatformViewInputConnection() {
* <p>See also: @{link lockPlatformViewInputConnection}.
*/
public void unlockPlatformViewInputConnection() {
isInputConnectionLocked = false;
if (inputTarget.type == InputTarget.Type.VD_PLATFORM_VIEW) {
isInputConnectionLocked = false;
}
}

/**
Expand Down Expand Up @@ -293,10 +295,21 @@ public InputConnection createInputConnection(
return null;
}

if (inputTarget.type == InputTarget.Type.PLATFORM_VIEW) {
if (inputTarget.type == InputTarget.Type.HC_PLATFORM_VIEW) {
return null;
}

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

outAttrs.inputType =
inputTypeFromTextInputType(
configuration.inputType,
Expand Down Expand Up @@ -351,7 +364,9 @@ public InputConnection getLastInputConnection() {
* input connection.
*/
public void clearPlatformViewClient(int platformViewId) {
if (inputTarget.type == InputTarget.Type.PLATFORM_VIEW && inputTarget.id == platformViewId) {
if ((inputTarget.type == InputTarget.Type.VD_PLATFORM_VIEW
|| inputTarget.type == InputTarget.Type.HC_PLATFORM_VIEW)
&& inputTarget.id == platformViewId) {
inputTarget = new InputTarget(InputTarget.Type.NO_TARGET, 0);
notifyViewExited();
mImm.hideSoftInputFromWindow(mView.getApplicationWindowToken(), 0);
Expand Down Expand Up @@ -412,13 +427,25 @@ void setTextInputClient(int client, TextInputChannel.Configuration configuration
// setTextInputClient will be followed by a call to setTextInputEditingState.
// Do a restartInput at that time.
mRestartInputPending = true;
unlockPlatformViewInputConnection();
lastClientRect = null;
mEditable.addEditingStateListener(this);
}

private void setPlatformViewTextInputClient(int platformViewId) {
inputTarget = new InputTarget(InputTarget.Type.PLATFORM_VIEW, platformViewId);
lastInputConnection = null;
private void setPlatformViewTextInputClient(int platformViewId, boolean usesVirtualDisplay) {
if (usesVirtualDisplay) {
// We need to make sure that the Flutter view is focused so that no imm operations get short
// circuited.
// Not asking for focus here specifically manifested in a but on API 28 devices where the
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo: "bug"

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
// Not asking for focus here specifically manifested in a but on API 28 devices where the
// Not asking for focus here specifically manifested in a bug on API 28 devices where the

// platform view's request to show a keyboard was ignored.
mView.requestFocus();
inputTarget = new InputTarget(InputTarget.Type.VD_PLATFORM_VIEW, platformViewId);
mImm.restartInput(mView);
mRestartInputPending = false;
} else {
inputTarget = new InputTarget(InputTarget.Type.HC_PLATFORM_VIEW, platformViewId);
lastInputConnection = null;
}
}

private static boolean composingChanged(
Expand Down Expand Up @@ -509,10 +536,35 @@ public void inspect(double x, double y) {

@VisibleForTesting
void clearTextInputClient() {
if (inputTarget.type == InputTarget.Type.VD_PLATFORM_VIEW) {
// This only applies to platform views that use a virtual display.
// 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 view's
// 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;
}
mEditable.removeEditingStateListener(this);
notifyViewExited();
updateAutofillConfigurationIfNeeded(null);
inputTarget = new InputTarget(InputTarget.Type.NO_TARGET, 0);
unlockPlatformViewInputConnection();
lastClientRect = null;
}

Expand All @@ -522,9 +574,12 @@ enum Type {
// InputConnection is managed by the TextInputPlugin, and events are forwarded to the Flutter
// framework.
FRAMEWORK_CLIENT,
// InputConnection is managed by a platform view that is embeded in the Android view
// hierarchy.
PLATFORM_VIEW,
// InputConnection is managed by an embedded platform view that is backed by a virtual
// display (VD).
VD_PLATFORM_VIEW,
// InputConnection is managed by an embedded platform view that is embeded in the Android view
// hierarchy, and uses hybrid composition (HC).
HC_PLATFORM_VIEW,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: avoid abbreviations, VIRTUAL_DISPLAY_PLATFORM_VIEW, HYBRID_COMPOSITION_PLATFORM_VIEW

nit: please explain a bit more about what hybrid composition is - that's the one that uses ImageView right?

}

public InputTarget(@NonNull Type type, int id) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ public interface PlatformViewsAccessibilityDelegate {
@Nullable
View getPlatformViewById(int viewId);

/** Returns true if the platform view uses virtual displays. */
boolean usesVirtualDisplay(int id);

/**
* Attaches an accessibility bridge for this platform views accessibility delegate.
*
Expand Down
Loading