[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
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt
index b891792..8601b3d 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/SceneWindowRootView.kt
@@ -24,8 +24,10 @@
viewModel: SceneContainerViewModel,
containerConfig: SceneContainerConfig,
scenes: Set<Scene>,
+ layoutInsetController: LayoutInsetsController,
) {
this.viewModel = viewModel
+ setLayoutInsetsController(layoutInsetController)
SceneWindowRootViewBinder.bind(
view = this@SceneWindowRootView,
viewModel = viewModel,
diff --git a/packages/SystemUI/src/com/android/systemui/scene/ui/view/WindowRootView.kt b/packages/SystemUI/src/com/android/systemui/scene/ui/view/WindowRootView.kt
index 860ebcb..c9a73e6 100644
--- a/packages/SystemUI/src/com/android/systemui/scene/ui/view/WindowRootView.kt
+++ b/packages/SystemUI/src/com/android/systemui/scene/ui/view/WindowRootView.kt
@@ -1,9 +1,15 @@
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 @@
attrs,
) {
+ private lateinit var layoutInsetsController: LayoutInsetsController
+ private var leftInset = 0
+ private var rightInset = 0
+
override fun onAttachedToWindow() {
super.onAttachedToWindow()
@@ -32,8 +42,114 @@
}
}
+ 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()
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
index 2b62b7d..a9c4aeb 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/shade/NotificationShadeWindowView.java
@@ -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.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.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 @@
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,7 +67,6 @@
private ViewTreeObserver.OnPreDrawListener mFloatingToolbarPreDrawListener;
private InteractionEventHandler mInteractionEventHandler;
- private LayoutInsetsController mLayoutInsetProvider;
public NotificationShadeWindowView(Context context, AttributeSet attrs) {
super(context, attrs);
@@ -87,64 +74,6 @@
}
@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();
setWillNotDraw(!DEBUG);
@@ -172,10 +101,6 @@
mInteractionEventHandler = listener;
}
- protected void setLayoutInsetsController(LayoutInsetsController provider) {
- mLayoutInsetProvider = provider;
- }
-
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
Boolean result = mInteractionEventHandler.handleDispatchTouchEvent(ev);
@@ -227,24 +152,6 @@
}
}
- 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 @@
}
}
- /**
- * 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
diff --git a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
index fc6479e..e02c427 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/ShadeViewProviderModule.kt
@@ -42,6 +42,7 @@
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 @@
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 @@
viewModel = viewModelProvider.get(),
containerConfig = containerConfigProvider.get(),
scenes = scenesProvider.get(),
+ layoutInsetController = layoutInsetController,
)
sceneWindowRootView
} else {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInsetsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInsetsController.java
index 39d7d66..27f42c63 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInsetsController.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInsetsController.java
@@ -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 {
}