From 8f20646bb54958906499ca2eb6835c2a8521d57f Mon Sep 17 00:00:00 2001 From: Alejandro Nijamkin Date: Thu, 20 Jul 2023 17:10:34 -0700 Subject: [PATCH] [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 Merged-In: I05cc4202bae1530506f6f0c90afdcda03ad7d020 --- .../scene/ui/view/SceneWindowRootView.kt | 2 + .../systemui/scene/ui/view/WindowRootView.kt | 111 ++++++++++++++++++ .../shade/NotificationShadeWindowView.java | 105 ----------------- .../systemui/shade/ShadeViewProviderModule.kt | 3 + .../NotificationInsetsController.java | 4 +- 5 files changed, 118 insertions(+), 107 deletions(-) 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 b89179289a3df..8601b3de2f7c7 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 @@ class SceneWindowRootView( viewModel: SceneContainerViewModel, containerConfig: SceneContainerConfig, scenes: Set, + 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 11e1eb910b1fd..4afe6797cdfbc 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 /** @@ -25,6 +31,10 @@ open class WindowRootView( attrs, ) { + private lateinit var layoutInsetsController: LayoutInsetsController + private var leftInset = 0 + private var rightInset = 0 + override fun onAttachedToWindow() { super.onAttachedToWindow() @@ -41,6 +51,67 @@ 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 = + 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. * @@ -50,4 +121,44 @@ open class WindowRootView( // 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 + } + + 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 2b62b7d67c2a4..a9c4aebe7ed69 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.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 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 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 fc6479eb62a49..e02c4275f095d 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.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, @Named(SceneContainerNames.SYSTEM_UI_DEFAULT) scenesProvider: Provider>, + 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 { diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInsetsController.java b/packages/SystemUI/src/com/android/systemui/statusbar/NotificationInsetsController.java index 39d7d6675ed44..27f42c632cc3c 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 { }