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

Commit 6e3cd07e authored by Johannes Gallmann's avatar Johannes Gallmann Committed by Android (Google) Code Review
Browse files

Merge "Fix back swipes/presses ignored during IME hide animation" into main

parents ce85a212 e6069c98
Loading
Loading
Loading
Loading
+9 −2
Original line number Diff line number Diff line
@@ -33,6 +33,7 @@ import android.util.Log;
import android.view.animation.BackGestureInterpolator;
import android.view.animation.Interpolator;
import android.view.animation.PathInterpolator;
import android.view.inputmethod.Flags;
import android.view.inputmethod.ImeTracker;
import android.window.BackEvent;
import android.window.OnBackAnimationCallback;
@@ -142,10 +143,16 @@ public class ImeBackAnimationController implements OnBackAnimationCallback {
            // control has been cancelled by the system. This can happen in multi-window mode for
            // example (i.e. split-screen or activity-embedding)
            notifyHideIme();
            return;
        }
        } else {
            startPostCommitAnim(/*hideIme*/ true);
        }
        if (Flags.refactorInsetsController()) {
            // Unregister all IME back callbacks so that back events are sent to the next callback
            // even while the hide animation is playing
            mInsetsController.getHost().getInputMethodManager().getImeOnBackInvokedDispatcher()
                    .preliminaryClear();
        }
    }

    private void setPreCommitProgress(float progress) {
        if (isHideAnimationInProgress()) return;
+13 −0
Original line number Diff line number Diff line
@@ -1344,6 +1344,11 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
            boolean fromPredictiveBack) {
        final boolean visible = layoutInsetsDuringAnimation == LAYOUT_INSETS_DURING_ANIMATION_SHOWN;

        if (Flags.refactorInsetsController() && !fromPredictiveBack && !visible
                && (types & ime()) != 0 && (mRequestedVisibleTypes & ime()) != 0) {
            // Clear IME back callbacks if a IME hide animation is requested
            mHost.getInputMethodManager().getImeOnBackInvokedDispatcher().preliminaryClear();
        }
        // Basically, we accept the requested visibilities from the upstream callers...
        setRequestedVisibleTypes(visible ? types : 0, types);

@@ -1921,6 +1926,14 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        final @InsetsType int requestedVisibleTypes =
                (mRequestedVisibleTypes & ~mask) | (visibleTypes & mask);
        if (mRequestedVisibleTypes != requestedVisibleTypes) {
            if (Flags.refactorInsetsController() && (mRequestedVisibleTypes & ime()) == 0
                    && (requestedVisibleTypes & ime()) != 0) {
                // In case the IME back callbacks have been preliminarily cleared before, let's
                // reregister them. This can happen if an IME hide animation was interrupted and the
                // IME is requested to be shown again.
                getHost().getInputMethodManager().getImeOnBackInvokedDispatcher()
                        .undoPreliminaryClear();
            }
            ProtoLog.d(IME_INSETS_CONTROLLER, "Setting requestedVisibleTypes to %d (was %d)",
                    requestedVisibleTypes, mRequestedVisibleTypes);
            mRequestedVisibleTypes = requestedVisibleTypes;
+8 −0
Original line number Diff line number Diff line
@@ -3666,6 +3666,14 @@ public final class InputMethodManager {
                0 /* startInputFlags */, 0 /* softInputMode */, 0 /* windowFlags */);
    }

    /**
     * Returns the ImeOnBackInvokedDispatcher.
     * @hide
     */
    public ImeOnBackInvokedDispatcher getImeOnBackInvokedDispatcher() {
        return mImeDispatcher;
    }

    /**
     * Check the next served view if needs to start input.
     */
+28 −0
Original line number Diff line number Diff line
@@ -203,6 +203,34 @@ public class ImeOnBackInvokedDispatcher implements OnBackInvokedDispatcher, Parc
        mImeCallbacks.remove(callback);
    }

    /**
     * Unregisters all callbacks on the receiving dispatcher but keeps a reference of the callbacks
     * in case the clearance is reverted in
     * {@link ImeOnBackInvokedDispatcher#undoPreliminaryClear()}.
     */
    public void preliminaryClear() {
        // Unregister previously registered callbacks if there's any.
        if (getReceivingDispatcher() != null) {
            for (ImeOnBackInvokedCallback callback : mImeCallbacks) {
                getReceivingDispatcher().unregisterOnBackInvokedCallback(callback);
            }
        }
    }

    /**
     * Reregisters all callbacks on the receiving dispatcher that have previously been cleared by
     * calling {@link ImeOnBackInvokedDispatcher#preliminaryClear()}. This can happen if an IME hide
     * animation is interrupted causing the IME to reappear.
     */
    public void undoPreliminaryClear() {
        if (getReceivingDispatcher() != null) {
            for (ImeOnBackInvokedCallback callback : mImeCallbacks) {
                getReceivingDispatcher().registerOnBackInvokedCallbackUnchecked(callback,
                        callback.mPriority);
            }
        }
    }

    /** Clears all registered callbacks on the instance. */
    public void clear() {
        // Unregister previously registered callbacks if there's any.
+3 −3
Original line number Diff line number Diff line
@@ -161,7 +161,7 @@ public class ImeBackAnimationControllerTest {
        mBackAnimationController.onBackInvoked();
        // verify that InputMethodManager#notifyImeHidden is called (which is the case whenever
        // getInputMethodManager is called from ImeBackAnimationController)
        verify(mViewRootInsetsControllerHost, times(1)).getInputMethodManager();
        verify(mViewRootInsetsControllerHost, times(2)).getInputMethodManager();
        // verify that ImeBackAnimationController does not take control over IME insets
        verify(mInsetsController, never()).controlWindowInsetsAnimation(anyInt(), any(), any(),
                anyBoolean(), anyLong(), any(), anyInt(), anyBoolean());
@@ -180,7 +180,7 @@ public class ImeBackAnimationControllerTest {
        mBackAnimationController.onBackInvoked();
        // verify that InputMethodManager#notifyImeHidden is called (which is the case whenever
        // getInputMethodManager is called from ImeBackAnimationController)
        verify(mViewRootInsetsControllerHost, times(1)).getInputMethodManager();
        verify(mViewRootInsetsControllerHost, times(2)).getInputMethodManager();
        // verify that ImeBackAnimationController does not take control over IME insets
        verify(mInsetsController, never()).controlWindowInsetsAnimation(anyInt(), any(), any(),
                anyBoolean(), anyLong(), any(), anyInt(), anyBoolean());
@@ -300,7 +300,7 @@ public class ImeBackAnimationControllerTest {
            mBackAnimationController.onBackInvoked();
            // verify that InputMethodManager#notifyImeHidden is called (which is the case whenever
            // getInputMethodManager is called from ImeBackAnimationController)
            verify(mViewRootInsetsControllerHost, times(1)).getInputMethodManager();
            verify(mViewRootInsetsControllerHost, times(2)).getInputMethodManager();
        });
    }