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

Commit dc32a1e2 authored by kwaky's avatar kwaky
Browse files

Handle System Bar Inset properly for immersive mode.

If we enter immersive mode (that is, SystemBar is hidden due to
transient mode), inset from that system bar is not applied even when it
becomes visible.

To fix this, we are applying window inset to fit ignoring the visibility
of the system bar. Each overlay view can opt-in to use this functionality
by overriding shouldUseStableInsets's return value to true. It can also
use conditionals to change its return value dynamically (e.g. depending
on whether the IME is visible. See NotificationPanelViewController.)

Bug: 169612767
Test: Manual (see screen shots)
Change-Id: I9d0c460bd3b521f9e334c3f7c9d304e68593b6da
parent d8ba97d6
Loading
Loading
Loading
Loading
+1 −2
Original line number Original line Diff line number Diff line
@@ -25,8 +25,7 @@
    <ViewStub android:id="@+id/notification_panel_stub"
    <ViewStub android:id="@+id/notification_panel_stub"
              android:layout_width="match_parent"
              android:layout_width="match_parent"
              android:layout_height="match_parent"
              android:layout_height="match_parent"
              android:layout="@layout/notification_panel_container"
              android:layout="@layout/notification_panel_container"/>
              android:layout_marginBottom="@dimen/car_bottom_navigation_bar_height"/>


    <ViewStub android:id="@+id/keyguard_stub"
    <ViewStub android:id="@+id/keyguard_stub"
              android:layout_width="match_parent"
              android:layout_width="match_parent"
+10 −17
Original line number Original line Diff line number Diff line
@@ -32,6 +32,7 @@ import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.MotionEvent;
import android.view.View;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewGroup;
import android.view.WindowInsets;


import androidx.annotation.NonNull;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.RecyclerView;
@@ -82,7 +83,6 @@ public class NotificationPanelViewController extends OverlayPanelViewController
    private final StatusBarStateController mStatusBarStateController;
    private final StatusBarStateController mStatusBarStateController;
    private final boolean mEnableHeadsUpNotificationWhenNotificationShadeOpen;
    private final boolean mEnableHeadsUpNotificationWhenNotificationShadeOpen;
    private final NotificationVisibilityLogger mNotificationVisibilityLogger;
    private final NotificationVisibilityLogger mNotificationVisibilityLogger;
    private final int mNavBarHeight;


    private float mInitialBackgroundAlpha;
    private float mInitialBackgroundAlpha;
    private float mBackgroundAlphaDiff;
    private float mBackgroundAlphaDiff;
@@ -97,6 +97,7 @@ public class NotificationPanelViewController extends OverlayPanelViewController
    private boolean mNotificationListAtEndAtTimeOfTouch;
    private boolean mNotificationListAtEndAtTimeOfTouch;
    private boolean mIsSwipingVerticallyToClose;
    private boolean mIsSwipingVerticallyToClose;
    private boolean mIsNotificationCardSwiping;
    private boolean mIsNotificationCardSwiping;
    private boolean mImeVisible = false;


    private OnUnseenCountUpdateListener mUnseenCountUpdateListener;
    private OnUnseenCountUpdateListener mUnseenCountUpdateListener;


@@ -139,8 +140,6 @@ public class NotificationPanelViewController extends OverlayPanelViewController
        mStatusBarStateController = statusBarStateController;
        mStatusBarStateController = statusBarStateController;
        mNotificationVisibilityLogger = notificationVisibilityLogger;
        mNotificationVisibilityLogger = notificationVisibilityLogger;


        mNavBarHeight = mResources.getDimensionPixelSize(R.dimen.car_bottom_navigation_bar_height);

        mCommandQueue.addCallback(this);
        mCommandQueue.addCallback(this);


        // Notification background setup.
        // Notification background setup.
@@ -189,19 +188,7 @@ public class NotificationPanelViewController extends OverlayPanelViewController
        if (mContext.getDisplayId() != displayId) {
        if (mContext.getDisplayId() != displayId) {
            return;
            return;
        }
        }
        boolean isKeyboardVisible = (vis & InputMethodService.IME_VISIBLE) != 0;
        mImeVisible = (vis & InputMethodService.IME_VISIBLE) != 0;
        int bottomMargin = isKeyboardVisible ? 0 : mNavBarHeight;
        ViewGroup container = (ViewGroup) getLayout();
        if (container == null) {
            // Notification panel hasn't been inflated before. We shouldn't try to update the layout
            // params.
            return;
        }

        ViewGroup.MarginLayoutParams params =
                (ViewGroup.MarginLayoutParams) container.getLayoutParams();
        params.setMargins(params.leftMargin, params.topMargin, params.rightMargin, bottomMargin);
        container.setLayoutParams(params);
    }
    }


    // OverlayViewController
    // OverlayViewController
@@ -229,7 +216,7 @@ public class NotificationPanelViewController extends OverlayPanelViewController


    @Override
    @Override
    protected int getInsetTypesToFit() {
    protected int getInsetTypesToFit() {
        return 0;
        return WindowInsets.Type.navigationBars();
    }
    }


    @Override
    @Override
@@ -237,6 +224,12 @@ public class NotificationPanelViewController extends OverlayPanelViewController
        return mEnableHeadsUpNotificationWhenNotificationShadeOpen;
        return mEnableHeadsUpNotificationWhenNotificationShadeOpen;
    }
    }


    @Override
    protected boolean shouldUseStableInsets() {
        // When IME is visible, then the inset from the nav bar should not be applied.
        return !mImeVisible;
    }

    /** Reinflates the view. */
    /** Reinflates the view. */
    public void reinflate() {
    public void reinflate() {
        ViewGroup container = (ViewGroup) getLayout();
        ViewGroup container = (ViewGroup) getLayout();
+13 −0
Original line number Original line Diff line number Diff line
@@ -167,6 +167,19 @@ public class OverlayViewController {
        return true;
        return true;
    }
    }


    /**
     * Returns {@code true} if the window should use stable insets. Using stable insets means that
     * even when system bars are temporarily not visible, inset from the system bars will still be
     * applied.
     *
     * NOTE: When system bars are hidden in transient mode, insets from them will not be applied
     * even when the system bars become visible. Setting the return value to {@true} here can
     * prevent the OverlayView from overlapping with the system bars when that happens.
     */
    protected boolean shouldUseStableInsets() {
        return false;
    }

    /**
    /**
     * Returns the insets types to fit to the sysui overlay window when this
     * Returns the insets types to fit to the sysui overlay window when this
     * {@link OverlayViewController} is in the foreground.
     * {@link OverlayViewController} is in the foreground.
+8 −0
Original line number Original line Diff line number Diff line
@@ -108,6 +108,7 @@ public class OverlayViewGlobalStateController {
        if (mZOrderVisibleSortedMap.isEmpty()) {
        if (mZOrderVisibleSortedMap.isEmpty()) {
            setWindowVisible(true);
            setWindowVisible(true);
        }
        }

        if (!(viewController instanceof OverlayPanelViewController)) {
        if (!(viewController instanceof OverlayPanelViewController)) {
            inflateView(viewController);
            inflateView(viewController);
        }
        }
@@ -117,6 +118,7 @@ public class OverlayViewGlobalStateController {
        }
        }


        updateInternalsWhenShowingView(viewController);
        updateInternalsWhenShowingView(viewController);
        refreshUseStableInsets();
        refreshInsetTypesToFit();
        refreshInsetTypesToFit();
        refreshWindowFocus();
        refreshWindowFocus();
        refreshNavigationBarVisibility();
        refreshNavigationBarVisibility();
@@ -190,6 +192,7 @@ public class OverlayViewGlobalStateController {


        mZOrderVisibleSortedMap.remove(mZOrderMap.get(viewController));
        mZOrderVisibleSortedMap.remove(mZOrderMap.get(viewController));
        refreshHighestZOrderWhenHidingView(viewController);
        refreshHighestZOrderWhenHidingView(viewController);
        refreshUseStableInsets();
        refreshInsetTypesToFit();
        refreshInsetTypesToFit();
        refreshWindowFocus();
        refreshWindowFocus();
        refreshNavigationBarVisibility();
        refreshNavigationBarVisibility();
@@ -247,6 +250,11 @@ public class OverlayViewGlobalStateController {
        setWindowFocusable(mHighestZOrder == null ? false : mHighestZOrder.shouldFocusWindow());
        setWindowFocusable(mHighestZOrder == null ? false : mHighestZOrder.shouldFocusWindow());
    }
    }


    private void refreshUseStableInsets() {
        mSystemUIOverlayWindowController.setUsingStableInsets(
                mHighestZOrder == null ? false : mHighestZOrder.shouldUseStableInsets());
    }

    private void refreshInsetTypesToFit() {
    private void refreshInsetTypesToFit() {
        if (mZOrderVisibleSortedMap.isEmpty()) {
        if (mZOrderVisibleSortedMap.isEmpty()) {
            setFitInsetsTypes(statusBars());
            setFitInsetsTypes(statusBars());
+6 −0
Original line number Original line Diff line number Diff line
@@ -53,6 +53,7 @@ public class SystemUIOverlayWindowController implements
    private boolean mIsAttached = false;
    private boolean mIsAttached = false;
    private boolean mVisible = false;
    private boolean mVisible = false;
    private boolean mFocusable = false;
    private boolean mFocusable = false;
    private boolean mUsingStableInsets = false;


    @Inject
    @Inject
    public SystemUIOverlayWindowController(
    public SystemUIOverlayWindowController(
@@ -115,6 +116,7 @@ public class SystemUIOverlayWindowController implements
    /** Sets the types of insets to fit. Note: This should be rarely used. */
    /** Sets the types of insets to fit. Note: This should be rarely used. */
    public void setFitInsetsTypes(@WindowInsets.Type.InsetsType int types) {
    public void setFitInsetsTypes(@WindowInsets.Type.InsetsType int types) {
        mLpChanged.setFitInsetsTypes(types);
        mLpChanged.setFitInsetsTypes(types);
        mLpChanged.setFitInsetsIgnoringVisibility(mUsingStableInsets);
        updateWindow();
        updateWindow();
    }
    }


@@ -159,6 +161,10 @@ public class SystemUIOverlayWindowController implements
        return mFocusable;
        return mFocusable;
    }
    }


    protected void setUsingStableInsets(boolean useStableInsets) {
        mUsingStableInsets = useStableInsets;
    }

    private void updateWindow() {
    private void updateWindow() {
        if (mLp != null && mLp.copyFrom(mLpChanged) != 0) {
        if (mLp != null && mLp.copyFrom(mLpChanged) != 0) {
            if (isAttached()) {
            if (isAttached()) {