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

Commit a8e90c7c authored by Ming-Shin Lu's avatar Ming-Shin Lu Committed by Android (Google) Code Review
Browse files

Merge "Don't skip IME animation when backed to Task has no editor focus" into sc-dev

parents 164eb20e 5a810c84
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -51,8 +51,8 @@ public final class ImeInsetsSourceConsumer extends InsetsSourceConsumer {
    }
    }


    @Override
    @Override
    public void onWindowFocusGained() {
    public void onWindowFocusGained(boolean hasViewFocus) {
        super.onWindowFocusGained();
        super.onWindowFocusGained(hasViewFocus);
        getImm().registerImeConsumer(this);
        getImm().registerImeConsumer(this);
    }
    }


+5 −4
Original line number Original line Diff line number Diff line
@@ -1302,8 +1302,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
    /**
    /**
     * Called when current window gains focus.
     * Called when current window gains focus.
     */
     */
    public void onWindowFocusGained() {
    public void onWindowFocusGained(boolean hasViewFocused) {
        getSourceConsumer(ITYPE_IME).onWindowFocusGained();
        getSourceConsumer(ITYPE_IME).onWindowFocusGained(hasViewFocused);
    }
    }


    /**
    /**
@@ -1366,8 +1366,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
            final InsetsSourceControl imeControl = consumer != null ? consumer.getControl() : null;
            final InsetsSourceControl imeControl = consumer != null ? consumer.getControl() : null;
            // Skip showing animation once that made by system for some reason.
            // Skip showing animation once that made by system for some reason.
            // (e.g. starting window with IME snapshot)
            // (e.g. starting window with IME snapshot)
            if (imeControl != null && show) {
            if (imeControl != null) {
                skipAnim = imeControl.getAndClearSkipAnimationOnce();
                skipAnim = imeControl.getAndClearSkipAnimationOnce() && show
                        && consumer.hasViewFocusWhenWindowFocusGain();
            }
            }
        }
        }
        applyAnimation(types, show, fromIme, skipAnim);
        applyAnimation(types, show, fromIme, skipAnim);
+11 −1
Original line number Original line Diff line number Diff line
@@ -81,6 +81,11 @@ public class InsetsSourceConsumer {
    private final Supplier<Transaction> mTransactionSupplier;
    private final Supplier<Transaction> mTransactionSupplier;
    private @Nullable InsetsSourceControl mSourceControl;
    private @Nullable InsetsSourceControl mSourceControl;
    private boolean mHasWindowFocus;
    private boolean mHasWindowFocus;

    /**
     * Whether the view has focus returned by {@link #onWindowFocusGained(boolean)}.
     */
    private boolean mHasViewFocusWhenWindowFocusGain;
    private Rect mPendingFrame;
    private Rect mPendingFrame;
    private Rect mPendingVisibleFrame;
    private Rect mPendingVisibleFrame;


@@ -223,8 +228,9 @@ public class InsetsSourceConsumer {
    /**
    /**
     * Called when current window gains focus
     * Called when current window gains focus
     */
     */
    public void onWindowFocusGained() {
    public void onWindowFocusGained(boolean hasViewFocus) {
        mHasWindowFocus = true;
        mHasWindowFocus = true;
        mHasViewFocusWhenWindowFocusGain = hasViewFocus;
    }
    }


    /**
    /**
@@ -238,6 +244,10 @@ public class InsetsSourceConsumer {
        return mHasWindowFocus;
        return mHasWindowFocus;
    }
    }


    boolean hasViewFocusWhenWindowFocusGain() {
        return mHasViewFocusWhenWindowFocusGain;
    }

    boolean applyLocalVisibilityOverride() {
    boolean applyLocalVisibilityOverride() {
        final InsetsSource source = mState.peekSource(mType);
        final InsetsSource source = mState.peekSource(mType);
        final boolean isVisible = source != null ? source.isVisible() : getDefaultVisibility(mType);
        final boolean isVisible = source != null ? source.isVisible() : getDefaultVisibility(mType);
+3 −3
Original line number Original line Diff line number Diff line
@@ -3344,8 +3344,9 @@ public final class ViewRootImpl implements ViewParent,
        }
        }
        // TODO (b/131181940): Make sure this doesn't leak Activity with mActivityConfigCallback
        // TODO (b/131181940): Make sure this doesn't leak Activity with mActivityConfigCallback
        // config changes.
        // config changes.
        final View focusedView = mView != null ? mView.findFocus() : null;
        if (hasWindowFocus) {
        if (hasWindowFocus) {
            mInsetsController.onWindowFocusGained();
            mInsetsController.onWindowFocusGained(focusedView != null /* hasViewFocused */);
        } else {
        } else {
            mInsetsController.onWindowFocusLost();
            mInsetsController.onWindowFocusLost();
        }
        }
@@ -3394,8 +3395,7 @@ public final class ViewRootImpl implements ViewParent,


            // Note: must be done after the focus change callbacks,
            // Note: must be done after the focus change callbacks,
            // so all of the view state is set up correctly.
            // so all of the view state is set up correctly.
            mImeFocusController.onPostWindowFocus(mView != null ? mView.findFocus() : null,
            mImeFocusController.onPostWindowFocus(focusedView, hasWindowFocus, mWindowAttributes);
                    hasWindowFocus, mWindowAttributes);


            if (hasWindowFocus) {
            if (hasWindowFocus) {
                // Clear the forward bit.  We can just do this directly, since
                // Clear the forward bit.  We can just do this directly, since
+46 −12
Original line number Original line Diff line number Diff line
@@ -97,7 +97,7 @@ public class ImeInsetsSourceConsumerTest {


        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            // test if setVisibility can show IME
            // test if setVisibility can show IME
            mImeConsumer.onWindowFocusGained();
            mImeConsumer.onWindowFocusGained(true);
            mController.show(WindowInsets.Type.ime(), true /* fromIme */);
            mController.show(WindowInsets.Type.ime(), true /* fromIme */);
            mController.cancelExistingAnimations();
            mController.cancelExistingAnimations();
            assertTrue(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
            assertTrue(mController.getSourceConsumer(ime.getType()).isRequestedVisible());
@@ -116,7 +116,7 @@ public class ImeInsetsSourceConsumerTest {


        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            // Request IME visible before control is available.
            // Request IME visible before control is available.
            mImeConsumer.onWindowFocusGained();
            mImeConsumer.onWindowFocusGained(true);
            mController.show(WindowInsets.Type.ime(), true /* fromIme */);
            mController.show(WindowInsets.Type.ime(), true /* fromIme */);


            // set control and verify visibility is applied.
            // set control and verify visibility is applied.
@@ -132,24 +132,58 @@ public class ImeInsetsSourceConsumerTest {
    }
    }


    @Test
    @Test
    public void testImeGetAndClearSkipAnimationOnce() {
    public void testImeGetAndClearSkipAnimationOnce_expectSkip() {
        // Expect IME animation will skipped when the IME is visible at first place.
        verifyImeGetAndClearSkipAnimationOnce(true /* hasWindowFocus */, true /* hasViewFocus */,
                true /* expectSkipAnim */);
    }

    @Test
    public void testImeGetAndClearSkipAnimationOnce_expectNoSkip() {
        // Expect IME animation will not skipped if previously no view focused when gained the
        // window focus and requesting the IME visible next time.
        verifyImeGetAndClearSkipAnimationOnce(true /* hasWindowFocus */, false /* hasViewFocus */,
                false /* expectSkipAnim */);
    }

    private void verifyImeGetAndClearSkipAnimationOnce(boolean hasWindowFocus, boolean hasViewFocus,
            boolean expectSkipAnim) {
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
        InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> {
            // Request IME visible before control is available.
            // Request IME visible before control is available.
            mImeConsumer.onWindowFocusGained();
            mImeConsumer.onWindowFocusGained(hasWindowFocus);
            final boolean imeVisible = hasWindowFocus && hasViewFocus;
            if (imeVisible) {
                mController.show(WindowInsets.Type.ime(), true /* fromIme */);
                mController.show(WindowInsets.Type.ime(), true /* fromIme */);
            }


            // set control and verify visibility is applied.
            // set control and verify visibility is applied.
            InsetsSourceControl control = Mockito.spy(
            InsetsSourceControl control = Mockito.spy(
                    new InsetsSourceControl(ITYPE_IME, mLeash, new Point(), Insets.NONE));
                    new InsetsSourceControl(ITYPE_IME, mLeash, new Point(), Insets.NONE));
            // Simulate IME source control set this flag when the target has starting window.
            // Simulate IME source control set this flag when the target has starting window.
            control.setSkipAnimationOnce(true);
            control.setSkipAnimationOnce(true);

            if (imeVisible) {
                // Verify IME applyAnimation should be triggered when control becomes available,
                // and expect skip animation state after getAndClearSkipAnimationOnce invoked.
                mController.onControlsChanged(new InsetsSourceControl[]{ control });
                verify(control).getAndClearSkipAnimationOnce();
                verify(mController).applyAnimation(eq(WindowInsets.Type.ime()),
                        eq(true) /* show */, eq(false) /* fromIme */,
                        eq(expectSkipAnim) /* skipAnim */);
            }

            // If previously hasViewFocus is false, verify when requesting the IME visible next
            // time will not skip animation.
            if (!hasViewFocus) {
                mController.show(WindowInsets.Type.ime(), true);
                mController.onControlsChanged(new InsetsSourceControl[]{ control });
                mController.onControlsChanged(new InsetsSourceControl[]{ control });
                // Verify IME show animation should be triggered when control becomes available and
                // Verify IME show animation should be triggered when control becomes available and
                // the animation will be skipped by getAndClearSkipAnimationOnce invoked.
                // the animation will be skipped by getAndClearSkipAnimationOnce invoked.
                verify(control).getAndClearSkipAnimationOnce();
                verify(control).getAndClearSkipAnimationOnce();
            verify(mController).applyAnimation(
                verify(mController).applyAnimation(eq(WindowInsets.Type.ime()),
                    eq(WindowInsets.Type.ime()), eq(true) /* show */, eq(false) /* fromIme */,
                        eq(true) /* show */, eq(true) /* fromIme */,
                    eq(true) /* skipAnim */);
                        eq(false) /* skipAnim */);
            }
        });
        });
    }
    }
}
}
Loading