summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopModeStatus.java37
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/desktopmode/DesktopTasksController.kt3
-rw-r--r--libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecoration.java83
-rw-r--r--libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/DesktopModeWindowDecorationTests.java77
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 3b6be8afb9e7..2f51278e3c80 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();
@@ -684,7 +697,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;
@@ -730,6 +743,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,