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

Commit c69224c7 authored by Alejandro Nijamkin's avatar Alejandro Nijamkin Committed by Ale Nijamkin
Browse files

[flexiglass] Make the window-view full-screen.

Before this CL, the window-view for the scene container (our root view)
was not full-screen; it was getting cut off by the top and bottom window
insets (status bar and nav bar). With this CL, that's no longer the case
and Flexiglass is now full-screen behind the status bar and nav bar.

The approach was to identify the pieces of the legacy
NotificationShadeWindowView and move them to the common base class of
that and of the newer SceneWindowRootView, which is WindowRootView.

Fix: 290984671
Test: manually verified that the bouncer scene extends to the top and
bottom of the display when Flexiglass is turned on but also when it's
turned off (no harm done).

Change-Id: I05cc4202bae1530506f6f0c90afdcda03ad7d020
parent 403bf25d
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -24,8 +24,10 @@ class SceneWindowRootView(
        viewModel: SceneContainerViewModel,
        containerConfig: SceneContainerConfig,
        scenes: Set<Scene>,
        layoutInsetController: LayoutInsetsController,
    ) {
        this.viewModel = viewModel
        setLayoutInsetsController(layoutInsetController)
        SceneWindowRootViewBinder.bind(
            view = this@SceneWindowRootView,
            viewModel = viewModel,
+116 −0
Original line number Diff line number Diff line
package com.android.systemui.scene.ui.view

import android.annotation.SuppressLint
import android.content.Context
import android.util.AttributeSet
import android.util.Pair
import android.view.DisplayCutout
import android.view.View
import android.view.WindowInsets
import android.widget.FrameLayout
import androidx.core.view.updateMargins
import com.android.systemui.R
import com.android.systemui.compose.ComposeFacade

/** A view that can serve as the root of the main SysUI window. */
@@ -16,6 +22,10 @@ open class WindowRootView(
        attrs,
    ) {

    private lateinit var layoutInsetsController: LayoutInsetsController
    private var leftInset = 0
    private var rightInset = 0

    override fun onAttachedToWindow() {
        super.onAttachedToWindow()

@@ -32,8 +42,114 @@ open class WindowRootView(
        }
    }

    override fun generateLayoutParams(attrs: AttributeSet?): FrameLayout.LayoutParams? {
        return LayoutParams(context, attrs)
    }

    override fun generateDefaultLayoutParams(): FrameLayout.LayoutParams? {
        return LayoutParams(
            FrameLayout.LayoutParams.MATCH_PARENT,
            FrameLayout.LayoutParams.MATCH_PARENT
        )
    }

    override fun onApplyWindowInsets(windowInsets: WindowInsets): WindowInsets? {
        val insets = windowInsets.getInsetsIgnoringVisibility(WindowInsets.Type.systemBars())
        if (fitsSystemWindows) {
            val paddingChanged = insets.top != paddingTop || insets.bottom != paddingBottom

            // Drop top inset, and pass through bottom inset.
            if (paddingChanged) {
                setPadding(0, 0, 0, 0)
            }
        } else {
            val changed =
                paddingLeft != 0 || paddingRight != 0 || paddingTop != 0 || paddingBottom != 0
            if (changed) {
                setPadding(0, 0, 0, 0)
            }
        }
        leftInset = 0
        rightInset = 0

        val displayCutout = rootWindowInsets.displayCutout
        val pairInsets: Pair<Int, Int> =
            layoutInsetsController.getinsets(windowInsets, displayCutout)
        leftInset = pairInsets.first
        rightInset = pairInsets.second
        applyMargins()
        return windowInsets
    }

    fun setLayoutInsetsController(layoutInsetsController: LayoutInsetsController) {
        this.layoutInsetsController = layoutInsetsController
    }

    private fun applyMargins() {
        val count = childCount
        for (i in 0 until count) {
            val child = getChildAt(i)
            if (child.layoutParams is LayoutParams) {
                val layoutParams = child.layoutParams as LayoutParams
                if (
                    !layoutParams.ignoreRightInset &&
                        (layoutParams.rightMargin != rightInset ||
                            layoutParams.leftMargin != leftInset)
                ) {
                    layoutParams.updateMargins(left = leftInset, right = rightInset)
                    child.requestLayout()
                }
            }
        }
    }

    /**
     * Returns `true` if this view is the true root of the view-hierarchy; `false` otherwise.
     *
     * Please see the class-level documentation to understand why this is possible.
     */
    private fun isRoot(): Boolean {
        // TODO(b/283300105): remove this check once there's only one subclass of WindowRootView.
        return parent.let { it !is View || it.id == android.R.id.content }
    }

    /** Controller responsible for calculating insets for the shade window. */
    interface LayoutInsetsController {

        /** Update the insets and calculate them accordingly. */
        fun getinsets(
            windowInsets: WindowInsets?,
            displayCutout: DisplayCutout?,
        ): Pair<Int, Int>
    }

    private class LayoutParams : FrameLayout.LayoutParams {
        var ignoreRightInset = false

        constructor(
            width: Int,
            height: Int,
        ) : super(
            width,
            height,
        )

        @SuppressLint("CustomViewStyleable")
        constructor(
            context: Context,
            attrs: AttributeSet?,
        ) : super(
            context,
            attrs,
        ) {
            val obtainedAttributes =
                context.obtainStyledAttributes(attrs, R.styleable.StatusBarWindowView_Layout)
            ignoreRightInset =
                obtainedAttributes.getBoolean(
                    R.styleable.StatusBarWindowView_Layout_ignoreRightInset,
                    false
                )
            obtainedAttributes.recycle()
        }
    }
}
+0 −105
Original line number Diff line number Diff line
@@ -17,19 +17,15 @@
package com.android.systemui.shade;

import static android.os.Trace.TRACE_TAG_APP;
import static android.view.WindowInsets.Type.systemBars;

import static com.android.systemui.statusbar.phone.CentralSurfaces.DEBUG;

import android.annotation.ColorInt;
import android.annotation.DrawableRes;
import android.annotation.LayoutRes;
import android.annotation.Nullable;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.TypedArray;
import android.graphics.Canvas;
import android.graphics.Insets;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
@@ -37,9 +33,7 @@ import android.net.Uri;
import android.os.Bundle;
import android.os.Trace;
import android.util.AttributeSet;
import android.util.Pair;
import android.view.ActionMode;
import android.view.DisplayCutout;
import android.view.InputQueue;
import android.view.KeyEvent;
import android.view.LayoutInflater;
@@ -51,13 +45,10 @@ import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowInsetsController;
import android.widget.FrameLayout;

import com.android.internal.view.FloatingActionMode;
import com.android.internal.widget.floatingtoolbar.FloatingToolbar;
import com.android.systemui.R;
import com.android.systemui.scene.ui.view.WindowRootView;

/**
@@ -68,9 +59,6 @@ import com.android.systemui.scene.ui.view.WindowRootView;
public class NotificationShadeWindowView extends WindowRootView {
    public static final String TAG = "NotificationShadeWindowView";

    private int mRightInset = 0;
    private int mLeftInset = 0;

    // Implements the floating action mode for TextView's Cut/Copy/Past menu. Normally provided by
    // DecorView, but since this is a special window we have to roll our own.
    private View mFloatingActionModeOriginatingView;
@@ -79,71 +67,12 @@ public class NotificationShadeWindowView extends WindowRootView {
    private ViewTreeObserver.OnPreDrawListener mFloatingToolbarPreDrawListener;

    private InteractionEventHandler mInteractionEventHandler;
    private LayoutInsetsController mLayoutInsetProvider;

    public NotificationShadeWindowView(Context context, AttributeSet attrs) {
        super(context, attrs);
        setMotionEventSplittingEnabled(false);
    }

    @Override
    public WindowInsets onApplyWindowInsets(WindowInsets windowInsets) {
        final Insets insets = windowInsets.getInsetsIgnoringVisibility(systemBars());
        if (getFitsSystemWindows()) {
            boolean paddingChanged = insets.top != getPaddingTop()
                    || insets.bottom != getPaddingBottom();

            // Drop top inset, and pass through bottom inset.
            if (paddingChanged) {
                setPadding(0, 0, 0, 0);
            }
        } else {
            boolean changed = getPaddingLeft() != 0
                    || getPaddingRight() != 0
                    || getPaddingTop() != 0
                    || getPaddingBottom() != 0;
            if (changed) {
                setPadding(0, 0, 0, 0);
            }
        }

        mLeftInset = 0;
        mRightInset = 0;
        DisplayCutout displayCutout = getRootWindowInsets().getDisplayCutout();
        Pair<Integer, Integer> pairInsets = mLayoutInsetProvider
                .getinsets(windowInsets, displayCutout);
        mLeftInset = pairInsets.first;
        mRightInset = pairInsets.second;
        applyMargins();
        return windowInsets;
    }

    private void applyMargins() {
        final int count = getChildCount();
        for (int i = 0; i < count; i++) {
            View child = getChildAt(i);
            if (child.getLayoutParams() instanceof LayoutParams) {
                LayoutParams lp = (LayoutParams) child.getLayoutParams();
                if (!lp.ignoreRightInset
                        && (lp.rightMargin != mRightInset || lp.leftMargin != mLeftInset)) {
                    lp.rightMargin = mRightInset;
                    lp.leftMargin = mLeftInset;
                    child.requestLayout();
                }
            }
        }
    }

    @Override
    public FrameLayout.LayoutParams generateLayoutParams(AttributeSet attrs) {
        return new LayoutParams(getContext(), attrs);
    }

    @Override
    protected FrameLayout.LayoutParams generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    }

    @Override
    protected void onAttachedToWindow() {
        super.onAttachedToWindow();
@@ -172,10 +101,6 @@ public class NotificationShadeWindowView extends WindowRootView {
        mInteractionEventHandler = listener;
    }

    protected void setLayoutInsetsController(LayoutInsetsController provider) {
        mLayoutInsetProvider = provider;
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Boolean result = mInteractionEventHandler.handleDispatchTouchEvent(ev);
@@ -227,24 +152,6 @@ public class NotificationShadeWindowView extends WindowRootView {
        }
    }

    private static class LayoutParams extends FrameLayout.LayoutParams {

        public boolean ignoreRightInset;

        LayoutParams(int width, int height) {
            super(width, height);
        }

        LayoutParams(Context c, AttributeSet attrs) {
            super(c, attrs);

            TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.StatusBarWindowView_Layout);
            ignoreRightInset = a.getBoolean(
                    R.styleable.StatusBarWindowView_Layout_ignoreRightInset, false);
            a.recycle();
        }
    }

    @Override
    public ActionMode startActionModeForChild(View originalView, ActionMode.Callback callback,
            int type) {
@@ -357,18 +264,6 @@ public class NotificationShadeWindowView extends WindowRootView {
        }
    }

    /**
     * Controller responsible for calculating insets for the shade window.
     */
    public interface LayoutInsetsController {

        /**
         * Update the insets and calculate them accordingly.
         */
        Pair<Integer, Integer> getinsets(@Nullable WindowInsets windowInsets,
                @Nullable DisplayCutout displayCutout);
    }

    interface InteractionEventHandler {
        /**
         * Returns a result for {@link ViewGroup#dispatchTouchEvent(MotionEvent)} or null to defer
+3 −0
Original line number Diff line number Diff line
@@ -42,6 +42,7 @@ import com.android.systemui.scene.ui.view.WindowRootView
import com.android.systemui.scene.ui.viewmodel.SceneContainerViewModel
import com.android.systemui.settings.UserTracker
import com.android.systemui.statusbar.LightRevealScrim
import com.android.systemui.statusbar.NotificationInsetsController
import com.android.systemui.statusbar.NotificationShelf
import com.android.systemui.statusbar.NotificationShelfController
import com.android.systemui.statusbar.notification.row.dagger.NotificationShelfComponent
@@ -78,6 +79,7 @@ abstract class ShadeViewProviderModule {
            containerConfigProvider: Provider<SceneContainerConfig>,
            @Named(SceneContainerNames.SYSTEM_UI_DEFAULT)
            scenesProvider: Provider<Set<@JvmSuppressWildcards Scene>>,
            layoutInsetController: NotificationInsetsController,
        ): WindowRootView {
            return if (
                featureFlags.isEnabled(Flags.SCENE_CONTAINER) && ComposeFacade.isComposeAvailable()
@@ -88,6 +90,7 @@ abstract class ShadeViewProviderModule {
                    viewModel = viewModelProvider.get(),
                    containerConfig = containerConfigProvider.get(),
                    scenes = scenesProvider.get(),
                    layoutInsetController = layoutInsetController,
                )
                sceneWindowRootView
            } else {
+2 −2
Original line number Diff line number Diff line
@@ -16,11 +16,11 @@

package com.android.systemui.statusbar;

import com.android.systemui.shade.NotificationShadeWindowView;
import com.android.systemui.scene.ui.view.WindowRootView;

/**
 * Calculates insets for the notification shade window view.
 */
public abstract class NotificationInsetsController
        implements NotificationShadeWindowView.LayoutInsetsController {
        implements WindowRootView.LayoutInsetsController {
}