Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 08c01f0d authored by Johannes Gallmann's avatar Johannes Gallmann
Browse files

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
parent 2fe6f173
Loading
Loading
Loading
Loading
+22 −0
Original line number Diff line number Diff line
@@ -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() {
+2 −1
Original line number Diff line number Diff line
@@ -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;
        }
    }
+13 −2
Original line number Diff line number Diff line
@@ -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) {