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

Commit 601f6eb6 authored by Cosmin Băieș's avatar Cosmin Băieș
Browse files

Revert^2 "Allow hiding the IME navigation bar"

Allow hiding the IME navigation bar

This implements a mechanism to allow IMEs to request hiding the IME
navigation bar (containing the IME collapse and IME switcher buttons)
using existing InsetsControllers API.

To make this work, the previous insetsSizeOverride for the IME set on
the system navigation bar was removed, and the IME navigation bar is now
treated as a caption bar internally, providing insets from its own
process.

Tests were fixed by providing a default implementation for
setImeCaptionBarInsetsHeight, and by handling ID_IME_CAPTION_BAR
in InsetsSource#calculateInsets.

42aaa57f

Test: atest
  InputMethodServiceTest#testRequestHideImeCaptionBar
  InputMethodServiceTest#testRequestHideThenShowImeCaptionBar
Bug: 292515843

Change-Id: I8793db69fb846046300d5a56b3b0060138ef4cd5
parent 92e3f280
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -576,6 +576,12 @@ public class InputMethodService extends AbstractInputMethodService {
    @EnabledSince(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
    public static final long DISALLOW_INPUT_METHOD_INTERFACE_OVERRIDE = 148086656L;

    /**
     * Enable the logic to allow hiding the IME caption bar ("fake" IME navigation bar).
     * @hide
     */
    public static final boolean ENABLE_HIDE_IME_CAPTION_BAR = false;

    LayoutInflater mInflater;
    TypedArray mThemeAttrs;
    @UnsupportedAppUsage
+33 −1
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package android.inputmethodservice;

import static android.inputmethodservice.InputMethodService.ENABLE_HIDE_IME_CAPTION_BAR;
import static android.view.WindowInsets.Type.captionBar;
import static android.view.WindowInsetsController.APPEARANCE_LIGHT_NAVIGATION_BARS;

import android.animation.ValueAnimator;
@@ -230,6 +232,16 @@ final class NavigationBarController {

            setIconTintInternal(calculateTargetDarkIntensity(mAppearance,
                    mDrawLegacyNavigationBarBackground));

            if (ENABLE_HIDE_IME_CAPTION_BAR) {
                mNavigationBarFrame.setOnApplyWindowInsetsListener((view, insets) -> {
                    if (mNavigationBarFrame != null) {
                        boolean visible = insets.isVisible(captionBar());
                        mNavigationBarFrame.setVisibility(visible ? View.VISIBLE : View.INVISIBLE);
                    }
                    return view.onApplyWindowInsets(insets);
                });
            }
        }

        private void uninstallNavigationBarFrameIfNecessary() {
@@ -240,6 +252,9 @@ final class NavigationBarController {
            if (parent instanceof ViewGroup) {
                ((ViewGroup) parent).removeView(mNavigationBarFrame);
            }
            if (ENABLE_HIDE_IME_CAPTION_BAR) {
                mNavigationBarFrame.setOnApplyWindowInsetsListener(null);
            }
            mNavigationBarFrame = null;
        }

@@ -414,9 +429,11 @@ final class NavigationBarController {
                        decor.bringChildToFront(mNavigationBarFrame);
                    }
                }
                if (!ENABLE_HIDE_IME_CAPTION_BAR) {
                    mNavigationBarFrame.setVisibility(View.VISIBLE);
                }
            }
        }

        @Override
        public void onNavButtonFlagsChanged(@InputMethodNavButtonFlags int navButtonFlags) {
@@ -435,6 +452,11 @@ final class NavigationBarController {
                    mShouldShowImeSwitcherWhenImeIsShown;
            mShouldShowImeSwitcherWhenImeIsShown = shouldShowImeSwitcherWhenImeIsShown;

            if (ENABLE_HIDE_IME_CAPTION_BAR) {
                mService.mWindow.getWindow().getDecorView().getWindowInsetsController()
                        .setImeCaptionBarInsetsHeight(getImeCaptionBarHeight());
            }

            if (imeDrawsImeNavBar) {
                installNavigationBarFrameIfNecessary();
                if (mNavigationBarFrame == null) {
@@ -528,6 +550,16 @@ final class NavigationBarController {
            return drawLegacyNavigationBarBackground;
        }

        /**
         * Returns the height of the IME caption bar if this should be shown, or {@code 0} instead.
         */
        private int getImeCaptionBarHeight() {
            return mImeDrawsImeNavBar
                    ? mService.getResources().getDimensionPixelSize(
                            com.android.internal.R.dimen.navigation_bar_frame_height)
                    : 0;
        }

        @Override
        public String toDebugString() {
            return "{mImeDrawsImeNavBar=" + mImeDrawsImeNavBar
+47 −1
Original line number Diff line number Diff line
@@ -16,10 +16,12 @@

package android.view;

import static android.inputmethodservice.InputMethodService.ENABLE_HIDE_IME_CAPTION_BAR;
import static android.os.Trace.TRACE_TAG_VIEW;
import static android.view.InsetsControllerProto.CONTROL;
import static android.view.InsetsControllerProto.STATE;
import static android.view.InsetsSource.ID_IME;
import static android.view.InsetsSource.ID_IME_CAPTION_BAR;
import static android.view.ViewRootImpl.CAPTION_ON_SHELL;
import static android.view.WindowInsets.Type.FIRST;
import static android.view.WindowInsets.Type.LAST;
@@ -40,6 +42,7 @@ import android.app.ActivityThread;
import android.content.Context;
import android.content.res.CompatibilityInfo;
import android.graphics.Insets;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.CancellationSignal;
import android.os.Handler;
@@ -652,6 +655,7 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
    private int mLastWindowingMode;
    private boolean mStartingAnimation;
    private int mCaptionInsetsHeight = 0;
    private int mImeCaptionBarInsetsHeight = 0;
    private boolean mAnimationsDisabled;
    private boolean mCompatSysUiVisibilityStaled;

@@ -693,6 +697,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
                    if (!CAPTION_ON_SHELL && source1.getType() == captionBar()) {
                        return;
                    }
                    if (source1.getId() == ID_IME_CAPTION_BAR) {
                        return;
                    }

                    // Don't change the indexes of the sources while traversing. Remove it later.
                    mPendingRemoveIndexes.add(index1);
@@ -823,6 +830,9 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        if (mFrame.equals(frame)) {
            return;
        }
        if (mImeCaptionBarInsetsHeight != 0) {
            setImeCaptionBarInsetsHeight(mImeCaptionBarInsetsHeight);
        }
        mHost.notifyInsetsChanged();
        mFrame.set(frame);
    }
@@ -1007,6 +1017,12 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        // Ensure to update all existing source consumers
        for (int i = mSourceConsumers.size() - 1; i >= 0; i--) {
            final InsetsSourceConsumer consumer = mSourceConsumers.valueAt(i);
            if (consumer.getId() == ID_IME_CAPTION_BAR) {
                // The inset control for the IME caption bar will never be dispatched
                // by the server.
                continue;
            }

            final InsetsSourceControl control = mTmpControlArray.get(consumer.getId());
            if (control != null) {
                controllableTypes |= control.getType();
@@ -1499,7 +1515,8 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
                continue;
            }
            final InsetsSourceControl control = consumer.getControl();
            if (control != null && control.getLeash() != null) {
            if (control != null
                    && (control.getLeash() != null || control.getId() == ID_IME_CAPTION_BAR)) {
                controls.put(control.getId(), new InsetsSourceControl(control));
                typesReady |= consumer.getType();
            }
@@ -1884,6 +1901,35 @@ public class InsetsController implements WindowInsetsController, InsetsAnimation
        }
    }

    @Override
    public void setImeCaptionBarInsetsHeight(int height) {
        if (!ENABLE_HIDE_IME_CAPTION_BAR) {
            return;
        }
        Rect newFrame = new Rect(mFrame.left, mFrame.bottom - height, mFrame.right, mFrame.bottom);
        InsetsSource source = mState.peekSource(ID_IME_CAPTION_BAR);
        if (mImeCaptionBarInsetsHeight != height
                || (source != null && !newFrame.equals(source.getFrame()))) {
            mImeCaptionBarInsetsHeight = height;
            if (mImeCaptionBarInsetsHeight != 0) {
                mState.getOrCreateSource(ID_IME_CAPTION_BAR, captionBar())
                        .setFrame(newFrame);
                getSourceConsumer(ID_IME_CAPTION_BAR, captionBar()).setControl(
                        new InsetsSourceControl(ID_IME_CAPTION_BAR, captionBar(),
                                null /* leash */, false /* initialVisible */,
                                new Point(), Insets.NONE),
                        new int[1], new int[1]);
            } else {
                mState.removeSource(ID_IME_CAPTION_BAR);
                InsetsSourceConsumer sourceConsumer = mSourceConsumers.get(ID_IME_CAPTION_BAR);
                if (sourceConsumer != null) {
                    sourceConsumer.setControl(null, new int[1], new int[1]);
                }
            }
            mHost.notifyInsetsChanged();
        }
    }

    @Override
    public void setSystemBarsBehavior(@Behavior int behavior) {
        mHost.setSystemBarsBehavior(behavior);
+9 −1
Original line number Diff line number Diff line
@@ -20,6 +20,7 @@ import static android.view.InsetsSourceProto.FRAME;
import static android.view.InsetsSourceProto.TYPE;
import static android.view.InsetsSourceProto.VISIBLE;
import static android.view.InsetsSourceProto.VISIBLE_FRAME;
import static android.view.WindowInsets.Type.captionBar;
import static android.view.WindowInsets.Type.ime;

import android.annotation.IntDef;
@@ -47,6 +48,9 @@ public class InsetsSource implements Parcelable {

    /** The insets source ID of IME */
    public static final int ID_IME = createId(null, 0, ime());
    /** The insets source ID of the IME caption bar ("fake" IME navigation bar). */
    static final int ID_IME_CAPTION_BAR =
            InsetsSource.createId(null /* owner */, 1 /* index */, captionBar());

    /**
     * Controls whether this source suppresses the scrim. If the scrim is ignored, the system won't
@@ -215,8 +219,12 @@ public class InsetsSource implements Parcelable {
        // During drag-move and drag-resizing, the caption insets position may not get updated
        // before the app frame get updated. To layout the app content correctly during drag events,
        // we always return the insets with the corresponding height covering the top.
        // However, with the "fake" IME navigation bar treated as a caption bar, we return the
        // insets with the corresponding height the bottom.
        if (getType() == WindowInsets.Type.captionBar()) {
            return Insets.of(0, frame.height(), 0, 0);
            return getId() == ID_IME_CAPTION_BAR
                    ? Insets.of(0, 0, 0, frame.height())
                    : Insets.of(0, frame.height(), 0, 0);
        }
        // Checks for whether there is shared edge with insets for 0-width/height window.
        final boolean hasIntersection = relativeFrame.isEmpty()
+9 −0
Original line number Diff line number Diff line
@@ -44,6 +44,7 @@ public class PendingInsetsController implements WindowInsetsController {
    private ArrayList<OnControllableInsetsChangedListener> mControllableInsetsChangedListeners
            = new ArrayList<>();
    private int mCaptionInsetsHeight = 0;
    private int mImeCaptionBarInsetsHeight = 0;
    private WindowInsetsAnimationControlListener mLoggingListener;
    private @InsetsType int mRequestedVisibleTypes = WindowInsets.Type.defaultVisible();

@@ -90,6 +91,11 @@ public class PendingInsetsController implements WindowInsetsController {
        mCaptionInsetsHeight = height;
    }

    @Override
    public void setImeCaptionBarInsetsHeight(int height) {
        mImeCaptionBarInsetsHeight = height;
    }

    @Override
    public void setSystemBarsBehavior(int behavior) {
        if (mReplayedInsetsController != null) {
@@ -168,6 +174,9 @@ public class PendingInsetsController implements WindowInsetsController {
        if (mCaptionInsetsHeight != 0) {
            controller.setCaptionInsetsHeight(mCaptionInsetsHeight);
        }
        if (mImeCaptionBarInsetsHeight != 0) {
            controller.setImeCaptionBarInsetsHeight(mImeCaptionBarInsetsHeight);
        }
        if (mAnimationsDisabled) {
            controller.setAnimationsDisabled(true);
        }
Loading