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

Commit 8f162c6e authored by Yohei Yukawa's avatar Yohei Yukawa
Browse files

DecorView#mNavigationGuard is gone

With this CL, DecorView#mNavigationGuard that handles navigation bar
only for IME windows [1] is finally gone and replaced with the
standard mechanism to handle navigation bar layout padding /
background color.

This CL addresses multiple anomalies regarding how the following APIs
work for IME windows.

 * Window#setNavigationBarColor()
   * Previous behavior:
    - Only works for Color#TRANSPARENT [2].
    - Ignores FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS.
   * New behavior:
    - Works as documented.
    - Requires FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS to work.

 * SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION flag
   * Previous behavior:
    - The system automatically sets
      SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION to the IME windows [3].
    - Does not work as documented. Content area is not extended to the
      navigation bar area.
    - Manually unsetting SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION can cause
      unexpected layout, because the system expects that this flag is
      always set to the IME window.
    - Had a special logic for FLAG_LAYOUT_IN_OVERSCAN [4].
   * New behavior:
    - Works as documented.
    - Can set/unset as necessary.

From the viewpoint of IME developers, this CL enables IME windows to
 * correctly extend the input view to the navigation bar region by
   using SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION as documented, instead of
   relying on a special hack with FLAG_LAYOUT_IN_OVERSCAN hack.
 * use Window#setNavigationBarColor() to easily change the navigation
   bar background color, like other non-floating windows.

Note that SYSTEM_UI_FLAG_LIGHT_NAVIGATION_BAR is not yet supported for
IME windows, which will be implemented in a subsequent CL.

 [1]: I6a93f30aec83f1cecfb854073046cbc87ab4aa66
      ae3349e1
 [2]: Iea77915ecc55eedaf19899e72c44f704ba9d852c
      0a9d1ea0
 [3]: I460912ee7c117480c57b947ed31eca330819f32c
      c68d577f
 [4]: Ic38f204a892bf34e8dae65990d5aa8c95af555d8
      9b32a35a
 [5]: I4b10a19641bd3ce6c43e7629404b6f202d4186e8

Fix: 25706186
Bug: 69002467
Test: ThemedNavBarKeyboard sample [5] works for the following cases
      * Extended Dark Navigation Bar
      * Separate Dark Navigation Bar
      * Floating Mode (if the target app uses dark navigation bar)
Change-Id: I664630099b6eb3fe31675444ba94944cb0eb98b0
parent 5fd1c97e
Loading
Loading
Loading
Loading
+6 −2
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.inputmethodservice;

import static android.view.ViewGroup.LayoutParams.MATCH_PARENT;
import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;

import android.annotation.CallSuper;
import android.annotation.DrawableRes;
@@ -852,6 +853,11 @@ public class InputMethodService extends AbstractInputMethodService {
                Context.LAYOUT_INFLATER_SERVICE);
        mWindow = new SoftInputWindow(this, "InputMethod", mTheme, null, null, mDispatcherState,
                WindowManager.LayoutParams.TYPE_INPUT_METHOD, Gravity.BOTTOM, false);
        // For ColorView in DecorView to work, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS needs to be set
        // by default (but IME developers can opt this out later if they want a new behavior).
        mWindow.getWindow().setFlags(
                FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS);

        initViews();
        mWindow.getWindow().setLayout(MATCH_PARENT, WRAP_CONTENT);
    }
@@ -882,8 +888,6 @@ public class InputMethodService extends AbstractInputMethodService {
        mThemeAttrs = obtainStyledAttributes(android.R.styleable.InputMethodService);
        mRootView = mInflater.inflate(
                com.android.internal.R.layout.input_method, null);
        mRootView.setSystemUiVisibility(
                View.SYSTEM_UI_FLAG_LAYOUT_STABLE | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
        mWindow.setContentView(mRootView);
        mRootView.getViewTreeObserver().removeOnComputeInternalInsetsListener(mInsetsComputer);
        mRootView.getViewTreeObserver().addOnComputeInternalInsetsListener(mInsetsComputer);
+6 −52
Original line number Diff line number Diff line
@@ -101,7 +101,6 @@ import static android.view.Window.DECOR_CAPTION_SHADE_LIGHT;
import static android.view.WindowManager.LayoutParams.FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS;
import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_OVERSCAN;
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION;
import static android.view.WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS;
@@ -194,8 +193,6 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind

    // View added at runtime to draw under the status bar area
    private View mStatusGuard;
    // View added at runtime to draw under the navigation bar area
    private View mNavigationGuard;

    private final ColorViewState mStatusColorViewState =
            new ColorViewState(STATUS_BAR_COLOR_VIEW_ATTRIBUTES);
@@ -1002,7 +999,6 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
        mFrameOffsets.set(insets.getSystemWindowInsets());
        insets = updateColorViews(insets, true /* animate */);
        insets = updateStatusGuard(insets);
        insets = updateNavigationGuard(insets);
        if (getForeground() != null) {
            drawableChanged();
        }
@@ -1062,7 +1058,10 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
        WindowManager.LayoutParams attrs = mWindow.getAttributes();
        int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility();

        if (!mWindow.mIsFloating) {
        // IME is an exceptional floating window that requires color view.
        final boolean isImeWindow =
                mWindow.getAttributes().type == WindowManager.LayoutParams.TYPE_INPUT_METHOD;
        if (!mWindow.mIsFloating || isImeWindow) {
            boolean disallowAnimate = !isLaidOut();
            disallowAnimate |= ((mLastWindowFlags ^ attrs.flags)
                    & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
@@ -1363,7 +1362,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
                        if (mStatusGuard == null) {
                            mStatusGuard = new View(mContext);
                            mStatusGuard.setBackgroundColor(mContext.getColor(
                                    R.color.input_method_navigation_guard));
                                    R.color.decor_view_status_guard));
                            addView(mStatusGuard, indexOfChild(mStatusColorViewState.view),
                                    new LayoutParams(LayoutParams.MATCH_PARENT,
                                            mlp.topMargin, Gravity.START | Gravity.TOP));
@@ -1407,51 +1406,6 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
        return insets;
    }

    private WindowInsets updateNavigationGuard(WindowInsets insets) {
        // IME windows lay out below the nav bar, but the content view must not (for back compat)
        // Only make this adjustment if the window is not requesting layout in overscan
        if (mWindow.getAttributes().type == WindowManager.LayoutParams.TYPE_INPUT_METHOD
                && (mWindow.getAttributes().flags & FLAG_LAYOUT_IN_OVERSCAN) == 0) {
            // prevent the content view from including the nav bar height
            if (mWindow.mContentParent != null) {
                if (mWindow.mContentParent.getLayoutParams() instanceof MarginLayoutParams) {
                    MarginLayoutParams mlp =
                            (MarginLayoutParams) mWindow.mContentParent.getLayoutParams();
                    mlp.bottomMargin = insets.getSystemWindowInsetBottom();
                    mWindow.mContentParent.setLayoutParams(mlp);
                }
            }
            // position the navigation guard view, creating it if necessary
            if (mNavigationGuard == null) {
                mNavigationGuard = new View(mContext);
                mNavigationGuard.setBackgroundColor(mContext.getColor(
                        R.color.input_method_navigation_guard));
                addView(mNavigationGuard, indexOfChild(mNavigationColorViewState.view),
                        new LayoutParams(LayoutParams.MATCH_PARENT,
                                insets.getSystemWindowInsetBottom(),
                                Gravity.START | Gravity.BOTTOM));
            } else {
                LayoutParams lp = (LayoutParams) mNavigationGuard.getLayoutParams();
                lp.height = insets.getSystemWindowInsetBottom();
                mNavigationGuard.setLayoutParams(lp);
            }
            updateNavigationGuardColor();
            insets = insets.consumeSystemWindowInsets(
                    false, false, false, true /* bottom */);
        }
        return insets;
    }

    void updateNavigationGuardColor() {
        if (mNavigationGuard != null) {
            // Make navigation bar guard invisible if the transparent color is specified.
            // Only TRANSPARENT is sufficient for hiding the navigation bar if the no software
            // keyboard is shown by IMS.
            mNavigationGuard.setVisibility(mWindow.getNavigationBarColor() == Color.TRANSPARENT ?
                    View.INVISIBLE : View.VISIBLE);
        }
    }

    /**
     * Overrides the view outline when the activity enters picture-in-picture to ensure that it has
     * an opaque shadow even if the window background is completely transparent. This only applies
@@ -2103,7 +2057,7 @@ public class DecorView extends FrameLayout implements RootViewSurfaceTaker, Wind
            for (int i = getChildCount() - 1; i >= 0; i--) {
                View v = getChildAt(i);
                if (v != mStatusColorViewState.view && v != mNavigationColorViewState.view
                        && v != mStatusGuard && v != mNavigationGuard) {
                        && v != mStatusGuard) {
                    removeViewAt(i);
                }
            }
+0 −1
Original line number Diff line number Diff line
@@ -3807,7 +3807,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
        mForcedNavigationBarColor = true;
        if (mDecor != null) {
            mDecor.updateColorViews(null, false /* animate */);
            mDecor.updateNavigationGuardColor();
        }
    }

+1 −1
Original line number Diff line number Diff line
@@ -73,7 +73,7 @@
    <drawable name="editbox_dropdown_light_frame">@drawable/editbox_dropdown_background</drawable>

    <drawable name="input_method_fullscreen_background">#fff9f9f9</drawable>
    <color name="input_method_navigation_guard">#ff000000</color>
    <color name="decor_view_status_guard">#ff000000</color>

    <!-- For date picker widget -->
    <drawable name="selected_day_background">#ff0092f4</drawable>
+1 −1
Original line number Diff line number Diff line
@@ -1812,7 +1812,7 @@
  <java-symbol type="bool" name="config_wimaxEnabled" />
  <java-symbol type="bool" name="show_ongoing_ime_switcher" />
  <java-symbol type="color" name="config_defaultNotificationColor" />
  <java-symbol type="color" name="input_method_navigation_guard" />
  <java-symbol type="color" name="decor_view_status_guard" />
  <java-symbol type="drawable" name="ic_notification_ime_default" />
  <java-symbol type="drawable" name="ic_menu_refresh" />
  <java-symbol type="drawable" name="ic_settings" />