summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Johannes Gallmann <gallmann@google.com> 2024-02-22 16:35:40 +0000
committer Johannes Gallmann <gallmann@google.com> 2024-04-18 13:45:46 +0000
commit08c01f0dbeb6f73b839edcfc02cc8eb7da63903b (patch)
tree135f188826e060adad84bed32eba1424f08e504e
parent2fe6f1737c7dafdb2f982a8c30fbba9db5f49ed1 (diff)
Unregister IME callback in onBackInvoked immediately
By removing the IME callback in onBackInvoked immediately, a new back gesture that starts during the IME hide animation can already dispatch to a new back callback. Currently, back gestures that start during the (predictive back) IME hide animation are simply ignored. This CL fixes that. Bug: 322836622 Flag: ACONFIG android.view.inputmethod.predictive_back_ime DISABLED Test: separate CL Change-Id: Iab628e23982915b5c5f17896436157794e90b649
-rw-r--r--core/java/android/view/ImeBackAnimationController.java22
-rw-r--r--core/java/android/view/ImeInsetsSourceConsumer.java3
-rw-r--r--core/java/android/view/InsetsController.java15
3 files changed, 37 insertions, 3 deletions
diff --git a/core/java/android/view/ImeBackAnimationController.java b/core/java/android/view/ImeBackAnimationController.java
index 665fac18be99..911f7b2d4ff6 100644
--- a/core/java/android/view/ImeBackAnimationController.java
+++ b/core/java/android/view/ImeBackAnimationController.java
@@ -31,9 +31,12 @@ import android.util.Log;
import android.view.animation.BackGestureInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
+import android.view.inputmethod.ImeTracker;
import android.window.BackEvent;
import android.window.OnBackAnimationCallback;
+import com.android.internal.inputmethod.SoftInputShowHideReason;
+
/**
* Controller for IME predictive back animation
*
@@ -192,6 +195,24 @@ public class ImeBackAnimationController implements OnBackAnimationCallback {
mPostCommitAnimator.setDuration(
triggerBack ? POST_COMMIT_DURATION_MS : POST_COMMIT_CANCEL_DURATION_MS);
mPostCommitAnimator.start();
+ if (triggerBack) {
+ mInsetsController.setPredictiveBackImeHideAnimInProgress(true);
+ notifyHideIme();
+ }
+ }
+
+ private void notifyHideIme() {
+ ImeTracker.Token statsToken = ImeTracker.forLogging().onStart(ImeTracker.TYPE_HIDE,
+ ImeTracker.ORIGIN_CLIENT,
+ SoftInputShowHideReason.HIDE_SOFT_INPUT_REQUEST_HIDE_WITH_CONTROL, true);
+ // This notifies the IME that it is being hidden. In response, the IME will unregister the
+ // animation callback, such that new back gestures happening during the post-commit phase of
+ // the hide animation can already dispatch to a new callback.
+ // Note that the IME will call hide() in InsetsController. InsetsController will not animate
+ // that hide request if it sees that ImeBackAnimationController is already animating
+ // the IME away
+ mInsetsController.getHost().getInputMethodManager()
+ .notifyImeHidden(mInsetsController.getHost().getWindowToken(), statsToken);
}
private void reset() {
@@ -200,6 +221,7 @@ public class ImeBackAnimationController implements OnBackAnimationCallback {
mLastProgress = 0f;
mTriggerBack = false;
mIsPreCommitAnimationInProgress = false;
+ mInsetsController.setPredictiveBackImeHideAnimInProgress(false);
}
private void resetPostCommitAnimator() {
diff --git a/core/java/android/view/ImeInsetsSourceConsumer.java b/core/java/android/view/ImeInsetsSourceConsumer.java
index 6caf4d6ff992..3def604e6739 100644
--- a/core/java/android/view/ImeInsetsSourceConsumer.java
+++ b/core/java/android/view/ImeInsetsSourceConsumer.java
@@ -243,7 +243,8 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
* {@link InputMethodManager#showSoftInput(View, int)} is called.
*/
public void onShowRequested() {
- if (mAnimationState == ANIMATION_STATE_HIDE) {
+ if (mAnimationState == ANIMATION_STATE_HIDE
+ || mController.isPredictiveBackImeHideAnimInProgress()) {
mHasPendingRequest = true;
}
}
diff --git a/core/java/android/view/InsetsController.java b/core/java/android/view/InsetsController.java
index 1f6cecafd68f..8c00fbb5023e 100644
--- a/core/java/android/view/InsetsController.java
+++ b/core/java/android/view/InsetsController.java
@@ -651,6 +651,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
private @Appearance int mAppearanceControlled;
private @Appearance int mAppearanceFromResource;
private boolean mBehaviorControlled;
+ private boolean mIsPredictiveBackImeHideAnimInProgress;
private final Runnable mPendingControlTimeout = this::abortPendingImeControlRequest;
private final ArrayList<OnControllableInsetsChangedListener> mControllableInsetsChangedListeners
@@ -1027,6 +1028,14 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
reportRequestedVisibleTypes();
}
+ void setPredictiveBackImeHideAnimInProgress(boolean isInProgress) {
+ mIsPredictiveBackImeHideAnimInProgress = isInProgress;
+ }
+
+ boolean isPredictiveBackImeHideAnimInProgress() {
+ return mIsPredictiveBackImeHideAnimInProgress;
+ }
+
@Override
public void show(@InsetsType int types) {
show(types, false /* fromIme */, null /* statsToken */);
@@ -1090,7 +1099,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
}
continue;
}
- if (fromIme && animationType == ANIMATION_TYPE_USER) {
+ if (fromIme && animationType == ANIMATION_TYPE_USER
+ && !mIsPredictiveBackImeHideAnimInProgress) {
// App is already controlling the IME, don't cancel it.
if (isIme) {
ImeTracker.forLogging().onFailed(
@@ -1186,7 +1196,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
}
}
if (!requestedVisible && animationType == ANIMATION_TYPE_NONE
- || animationType == ANIMATION_TYPE_HIDE) {
+ || animationType == ANIMATION_TYPE_HIDE || (animationType
+ == ANIMATION_TYPE_USER && mIsPredictiveBackImeHideAnimInProgress)) {
// no-op: already hidden or animating out (because window visibility is
// applied before starting animation).
if (isImeAnimation) {