diff options
| author | 2023-11-27 16:13:12 +0000 | |
|---|---|---|
| committer | 2024-01-02 15:18:56 +0000 | |
| commit | 159f9de407c1f79384312b51d038d71f5610b6b8 (patch) | |
| tree | 122657a39289b9301012ebc55989fcca5d0d50e3 | |
| parent | 237a75b1fcaad50520c2123ab80fb4f99d716d95 (diff) | |
Desktop Windowing: add sysprop flags for shadows and rounded corners
We add three flags:
1. Enable/disable rounded corners (boolean flag)
2. Enable/disable window shadows (boolean flag)
3. Enable/disable window shadows for the focused window (boolean flag) -
this flag only applies if flag 2 is disabled.
This CL does NOT update default bevahiours, i.e. in desktop mode, window
shadows and rounded corners are still shown by default.
adb commands: https://paste.googleplex.com/6310119139180544
Screenshot with rounded corners:
https://screenshot.googleplex.com/BHw6hDPnSa8a8yN.png
Screenshot without rounded corners:
https://screenshot.googleplex.com/98VVVd3Jk8y8dnF.png
Note: the screenshots don't seem to capture window shadows.
Bug: 316867234, 316865378
Test: unit tests for default behavior, ran adb commands to check sysprop
flags behavior
Change-Id: Iaafb50ebf82270c8e38bd957176d83ce6182a6dd
4 files changed, 167 insertions, 33 deletions
| diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java index dc82fc1b35dd..88949b2a5acd 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java @@ -55,6 +55,26 @@ public class DesktopModeStatus {              "persist.wm.debug.desktop_stashing", false);      /** +     * Flag to indicate whether to apply shadows to windows in desktop mode. +     */ +    private static final boolean USE_WINDOW_SHADOWS = SystemProperties.getBoolean( +            "persist.wm.debug.desktop_use_window_shadows", true); + +    /** +     * Flag to indicate whether to apply shadows to the focused window in desktop mode. +     * +     * Note: this flag is only relevant if USE_WINDOW_SHADOWS is false. +     */ +    private static final boolean USE_WINDOW_SHADOWS_FOCUSED_WINDOW = SystemProperties.getBoolean( +            "persist.wm.debug.desktop_use_window_shadows_focused_window", false); + +    /** +     * Flag to indicate whether to apply shadows to windows in desktop mode. +     */ +    private static final boolean USE_ROUNDED_CORNERS = SystemProperties.getBoolean( +            "persist.wm.debug.desktop_use_rounded_corners", true); + +    /**       * Return {@code true} is desktop windowing proto 2 is enabled       */      public static boolean isEnabled() { @@ -81,4 +101,21 @@ public class DesktopModeStatus {      public static boolean isStashingEnabled() {          return IS_STASHING_ENABLED;      } + +    /** +     * Return whether to use window shadows. +     * +     * @param isFocusedWindow whether the window to apply shadows to is focused +     */ +    public static boolean useWindowShadow(boolean isFocusedWindow) { +        return USE_WINDOW_SHADOWS +            || (USE_WINDOW_SHADOWS_FOCUSED_WINDOW && isFocusedWindow); +    } + +    /** +     * Return whether to use rounded corners for windows. +     */ +    public static boolean useRoundedCorners() { +        return USE_ROUNDED_CORNERS; +    }  } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt index 144555dd70c3..4a1bcaa7168a 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt @@ -721,6 +721,9 @@ class DesktopTasksController(              finishTransaction: SurfaceControl.Transaction      ) {          // Add rounded corners to freeform windows +        if (!DesktopModeStatus.useRoundedCorners()) { +            return +        }          val cornerRadius = ScreenDecorationsUtils.getWindowCornerRadius(context)          info.changes                  .filter { it.taskInfo?.windowingMode == WINDOWING_MODE_FREEFORM } diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java index 6ec91e0e28dd..7a9afc899327 100644 --- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java +++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java @@ -46,6 +46,7 @@ import android.view.ViewConfiguration;  import android.widget.ImageButton;  import android.window.WindowContainerTransaction; +import com.android.internal.annotations.VisibleForTesting;  import com.android.internal.policy.ScreenDecorationsUtils;  import com.android.launcher3.icons.BaseIconFactory;  import com.android.launcher3.icons.IconProvider; @@ -195,46 +196,16 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin      void relayout(ActivityManager.RunningTaskInfo taskInfo,              SurfaceControl.Transaction startT, SurfaceControl.Transaction finishT,              boolean applyStartTransactionOnDraw) { -        final int shadowRadiusID = taskInfo.isFocused -                ? R.dimen.freeform_decor_shadow_focused_thickness -                : R.dimen.freeform_decor_shadow_unfocused_thickness; -        final boolean isFreeform = -                taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM; -        final boolean isDragResizeable = isFreeform && taskInfo.isResizeable; -          if (isHandleMenuActive()) {              mHandleMenu.relayout(startT);          } +        updateRelayoutParams(mRelayoutParams, mContext, taskInfo, applyStartTransactionOnDraw); +          final WindowDecorLinearLayout oldRootView = mResult.mRootView;          final SurfaceControl oldDecorationSurface = mDecorationContainerSurface;          final WindowContainerTransaction wct = new WindowContainerTransaction(); -        final int windowDecorLayoutId = getDesktopModeWindowDecorLayoutId( -                taskInfo.getWindowingMode()); -        mRelayoutParams.reset(); -        mRelayoutParams.mRunningTaskInfo = taskInfo; -        mRelayoutParams.mLayoutResId = windowDecorLayoutId; -        mRelayoutParams.mCaptionHeightId = getCaptionHeightId(taskInfo.getWindowingMode()); -        mRelayoutParams.mShadowRadiusId = shadowRadiusID; -        mRelayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw; -        // The configuration used to lay out the window decoration. The system context's config is -        // used when the task density has been overridden to a custom density so that the resources -        // and views of the decoration aren't affected and match the rest of the System UI, if not -        // then just use the task's configuration. A copy is made instead of using the original -        // reference so that the configuration isn't mutated on config changes and diff checks can -        // be made in WindowDecoration#relayout using the pre/post-relayout configuration. -        // See b/301119301. -        // TODO(b/301119301): consider moving the config data needed for diffs to relayout params -        // instead of using a whole Configuration as a parameter. -        final Configuration windowDecorConfig = new Configuration(); -        windowDecorConfig.setTo(DesktopTasksController.isDesktopDensityOverrideSet() -                ? mContext.getResources().getConfiguration() // Use system context. -                : mTaskInfo.configuration); // Use task configuration. -        mRelayoutParams.mWindowDecorConfig = windowDecorConfig; - -        mRelayoutParams.mCornerRadius = -                (int) ScreenDecorationsUtils.getWindowCornerRadius(mContext);          relayout(mRelayoutParams, startT, finishT, wct, oldRootView, mResult);          // After this line, mTaskInfo is up-to-date and should be used instead of taskInfo @@ -273,6 +244,9 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin              closeMaximizeMenu();          } +        final boolean isFreeform = +                taskInfo.getWindowingMode() == WINDOWING_MODE_FREEFORM; +        final boolean isDragResizeable = isFreeform && taskInfo.isResizeable;          if (!isDragResizeable) {              if (!mTaskInfo.positionInParent.equals(mPositionInParent)) {                  // We still want to track caption bar's exclusion region on a non-resizeable task. @@ -323,6 +297,45 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin          }      } +    @VisibleForTesting +    static void updateRelayoutParams( +            RelayoutParams relayoutParams, +            Context context, +            ActivityManager.RunningTaskInfo taskInfo, +            boolean applyStartTransactionOnDraw) { +        relayoutParams.reset(); +        relayoutParams.mRunningTaskInfo = taskInfo; +        relayoutParams.mLayoutResId = +            getDesktopModeWindowDecorLayoutId(taskInfo.getWindowingMode()); +        relayoutParams.mCaptionHeightId = getCaptionHeightIdStatic(taskInfo.getWindowingMode()); +        if (DesktopModeStatus.useWindowShadow(/* isFocusedWindow= */ taskInfo.isFocused)) { +            relayoutParams.mShadowRadiusId = taskInfo.isFocused +                    ? R.dimen.freeform_decor_shadow_focused_thickness +                    : R.dimen.freeform_decor_shadow_unfocused_thickness; +        } +        relayoutParams.mApplyStartTransactionOnDraw = applyStartTransactionOnDraw; +        // The configuration used to lay out the window decoration. The system context's config is +        // used when the task density has been overridden to a custom density so that the resources +        // and views of the decoration aren't affected and match the rest of the System UI, if not +        // then just use the task's configuration. A copy is made instead of using the original +        // reference so that the configuration isn't mutated on config changes and diff checks can +        // be made in WindowDecoration#relayout using the pre/post-relayout configuration. +        // See b/301119301. +        // TODO(b/301119301): consider moving the config data needed for diffs to relayout params +        // instead of using a whole Configuration as a parameter. +        final Configuration windowDecorConfig = new Configuration(); +        windowDecorConfig.setTo(DesktopTasksController.isDesktopDensityOverrideSet() +                ? context.getResources().getConfiguration() // Use system context. +                : taskInfo.configuration); // Use task configuration. +        relayoutParams.mWindowDecorConfig = windowDecorConfig; + +        if (DesktopModeStatus.useRoundedCorners()) { +            relayoutParams.mCornerRadius = +                    (int) ScreenDecorationsUtils.getWindowCornerRadius(context); +        } +    } + +      private PointF calculateMaximizeMenuPosition() {          final PointF position = new PointF();          final Resources resources = mContext.getResources(); @@ -624,7 +637,7 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin          super.close();      } -    private int getDesktopModeWindowDecorLayoutId(@WindowingMode int windowingMode) { +    private static int getDesktopModeWindowDecorLayoutId(@WindowingMode int windowingMode) {          return windowingMode == WINDOWING_MODE_FREEFORM                  ? R.layout.desktop_mode_app_controls_window_decor                  : R.layout.desktop_mode_focused_window_decor; @@ -670,6 +683,10 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin      @Override      int getCaptionHeightId(@WindowingMode int windowingMode) { +        return getCaptionHeightIdStatic(windowingMode); +    } + +    private static int getCaptionHeightIdStatic(@WindowingMode int windowingMode) {          return windowingMode == WINDOWING_MODE_FULLSCREEN                  ? R.dimen.desktop_mode_fullscreen_decor_caption_height                  : R.dimen.desktop_mode_freeform_decor_caption_height; diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java index 18fcdd00df9d..77667ca579f2 100644 --- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java +++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java @@ -16,16 +16,24 @@  package com.android.wm.shell.windowdecor; +import static com.google.common.truth.Truth.assertThat; +  import static org.mockito.Mockito.any; +import static org.mockito.Mockito.anyInt;  import static org.mockito.Mockito.doReturn;  import static org.mockito.Mockito.spy;  import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when;  import android.app.ActivityManager;  import android.content.ComponentName;  import android.content.res.Configuration; +import android.content.res.Resources; +import android.content.res.TypedArray;  import android.os.Handler; +import android.os.SystemProperties;  import android.testing.AndroidTestingRunner; +import android.testing.TestableContext;  import android.view.Choreographer;  import android.view.Display;  import android.view.SurfaceControl; @@ -34,14 +42,17 @@ import android.window.WindowContainerTransaction;  import androidx.test.filters.SmallTest; +import com.android.internal.R;  import com.android.wm.shell.RootTaskDisplayAreaOrganizer;  import com.android.wm.shell.ShellTaskOrganizer;  import com.android.wm.shell.ShellTestCase;  import com.android.wm.shell.TestRunningTaskInfoBuilder;  import com.android.wm.shell.common.DisplayController;  import com.android.wm.shell.common.SyncTransactionQueue; +import com.android.wm.shell.windowdecor.WindowDecoration.RelayoutParams;  import org.junit.Before; +import org.junit.BeforeClass;  import org.junit.Test;  import org.junit.runner.RunWith;  import org.mockito.Mock; @@ -57,6 +68,13 @@ import java.util.function.Supplier;  @SmallTest  @RunWith(AndroidTestingRunner.class)  public class DesktopModeWindowDecorationTests extends ShellTestCase { +    private static final String USE_WINDOW_SHADOWS_SYSPROP_KEY = +            "persist.wm.debug.desktop_use_window_shadows"; +    private static final String FOCUSED_USE_WINDOW_SHADOWS_SYSPROP_KEY = +            "persist.wm.debug.desktop_use_window_shadows_focused_window"; +    private static final String USE_ROUNDED_CORNERS_SYSPROP_KEY = +            "persist.wm.debug.desktop_use_rounded_corners"; +      @Mock      private DisplayController mMockDisplayController;      @Mock @@ -79,14 +97,29 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {      private SurfaceControlViewHost mMockSurfaceControlViewHost;      @Mock      private WindowDecoration.SurfaceControlViewHostFactory mMockSurfaceControlViewHostFactory; +    @Mock +    private TypedArray mMockRoundedCornersRadiusArray;      private final Configuration mConfiguration = new Configuration(); +    private TestableContext mTestableContext; + +    /** Set up run before test class. */ +    @BeforeClass +    public static void setUpClass() { +        // Reset the sysprop settings before running the test. +        SystemProperties.set(USE_WINDOW_SHADOWS_SYSPROP_KEY, ""); +        SystemProperties.set(FOCUSED_USE_WINDOW_SHADOWS_SYSPROP_KEY, ""); +        SystemProperties.set(USE_ROUNDED_CORNERS_SYSPROP_KEY, ""); +    } +      @Before      public void setUp() {          doReturn(mMockSurfaceControlViewHost).when(mMockSurfaceControlViewHostFactory).create(                  any(), any(), any());          doReturn(mMockTransaction).when(mMockTransactionSupplier).get(); +        mTestableContext = new TestableContext(mContext); +        mTestableContext.ensureTestableResources();      }      @Test @@ -105,6 +138,50 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {      } +    @Test +    public void updateRelayoutParams_noSysPropFlagsSet_windowShadowsAreEnabled() { +        final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true); +        RelayoutParams relayoutParams = new RelayoutParams(); + +        DesktopModeWindowDecoration.updateRelayoutParams( +                relayoutParams, mContext, taskInfo, /* applyStartTransactionOnDraw= */ true); + +        assertThat(relayoutParams.mShadowRadiusId).isNotEqualTo(Resources.ID_NULL); +    } + +    @Test +    public void updateRelayoutParams_noSysPropFlagsSet_roundedCornersAreEnabled() { +        final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true); +        fillRoundedCornersResources(/* fillValue= */ 30); +        RelayoutParams relayoutParams = new RelayoutParams(); + +        DesktopModeWindowDecoration.updateRelayoutParams( +                relayoutParams, +                mTestableContext, +                taskInfo, +                /* applyStartTransactionOnDraw= */ true); + +        assertThat(relayoutParams.mCornerRadius).isGreaterThan(0); +    } + +    private void fillRoundedCornersResources(int fillValue) { +        when(mMockRoundedCornersRadiusArray.getDimensionPixelSize(anyInt(), anyInt())) +                .thenReturn(fillValue); +        mTestableContext.getOrCreateTestableResources().addOverride( +                R.array.config_roundedCornerRadiusArray, mMockRoundedCornersRadiusArray); +        mTestableContext.getOrCreateTestableResources().addOverride( +                R.dimen.rounded_corner_radius, fillValue); +        mTestableContext.getOrCreateTestableResources().addOverride( +                R.array.config_roundedCornerTopRadiusArray, mMockRoundedCornersRadiusArray); +        mTestableContext.getOrCreateTestableResources().addOverride( +                R.dimen.rounded_corner_radius_top, fillValue); +        mTestableContext.getOrCreateTestableResources().addOverride( +                R.array.config_roundedCornerBottomRadiusArray, mMockRoundedCornersRadiusArray); +        mTestableContext.getOrCreateTestableResources().addOverride( +                R.dimen.rounded_corner_radius_bottom, fillValue); +    } + +      private DesktopModeWindowDecoration createWindowDecoration(              ActivityManager.RunningTaskInfo taskInfo) {          return new DesktopModeWindowDecoration(mContext, mMockDisplayController, |