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

Commit 2b064078 authored by YCairn Overturf's avatar YCairn Overturf Committed by Cairn Overturf
Browse files

Add box shadows to freeform windows

See go/box-shadows-integration

This is component 1/4, just the freeform window.
Still remaining is the window menu, multi-instance menu and screen mode menu.

Dark Theme: snipit/AXYPDNdgoD8yUeo
Light Theme: snipit/C9EkaU6teNu4efA

Bug: b/367464660
Flag: com.android.window.flags.enable_freeform_box_shadows
Test: When the flag is enabled, freeform windows should match the spec in the design above
Change-Id: Ibc29ed8551c6d060a9d81ce8ba8795f241f86699
parent 7ed3b2ef
Loading
Loading
Loading
Loading
+14 −0
Original line number Diff line number Diff line
@@ -30,4 +30,18 @@
        <attr name="android:src" format="reference" />
        <attr name="android:drawableTint" format="color" />
    </declare-styleable>


    <declare-styleable name="BoxShadowSettings">
        <attr name="boxShadowBlurRadius" format="dimension" />
        <attr name="boxShadowSpreadRadius" format="dimension" />
        <attr name="boxShadowOffsetX" format="dimension" />
        <attr name="boxShadowOffsetY" format="dimension" />
        <attr name="boxShadowColor" format="color" />
    </declare-styleable>

    <declare-styleable name="BorderSettings">
        <attr name="borderStrokeWidth" format="dimension" />
        <attr name="borderColor" format="color" />
    </declare-styleable>
</resources>
+52 −0
Original line number Diff line number Diff line
@@ -145,4 +145,56 @@
        </item>
    </style>

    <style name="BoxShadowParamsKeyUnfocused">
        <item name="boxShadowColor">#0A000000</item>
        <item name="boxShadowOffsetX">0dp</item>
        <item name="boxShadowOffsetY">0dp</item>
        <item name="boxShadowBlurRadius">12dp</item>
        <item name="boxShadowSpreadRadius">0dp</item>
    </style>

    <style name="BoxShadowParamsKeyFocused">
        <item name="boxShadowColor">#19000000</item>
        <item name="boxShadowOffsetX">0dp</item>
        <item name="boxShadowOffsetY">0dp</item>
        <item name="boxShadowBlurRadius">24dp</item>
        <item name="boxShadowSpreadRadius">0dp</item>
    </style>

    <style name="BoxShadowParamsAmbientUnfocused">
        <item name="boxShadowColor">#1F000000</item>
        <item name="boxShadowOffsetX">0dp</item>
        <item name="boxShadowOffsetY">6dp</item>
        <item name="boxShadowBlurRadius">12dp</item>
        <item name="boxShadowSpreadRadius">0dp</item>
    </style>

    <style name="BoxShadowParamsAmbientFocused">
        <item name="boxShadowColor">#33000000</item>
        <item name="boxShadowOffsetX">0dp</item>
        <item name="boxShadowOffsetY">16dp</item>
        <item name="boxShadowBlurRadius">24dp</item>
        <item name="boxShadowSpreadRadius">0dp</item>
    </style>

    <style name="BorderSettingsUnfocusedLight">
        <item name="borderStrokeWidth">1dp</item>
        <item name="borderColor">#32BDC1C6</item>
    </style>

    <style name="BorderSettingsFocusedLight">
        <item name="borderStrokeWidth">1dp</item>
        <item name="borderColor">#4DBDC1C6</item>
    </style>

    <style name="BorderSettingsUnfocusedDark">
        <item name="borderStrokeWidth">1dp</item>
        <item name="borderColor">#339AA0A6</item>
    </style>

    <style name="BorderSettingsFocusedDark">
        <item name="borderStrokeWidth">1dp</item>
        <item name="borderColor">#579AA0A6</item>
    </style>

</resources>
+26 −2
Original line number Diff line number Diff line
@@ -104,6 +104,8 @@ import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
import com.android.wm.shell.shared.desktopmode.DesktopModeTransitionSource;
import com.android.wm.shell.shared.multiinstance.ManageWindowsViewContainer;
import com.android.wm.shell.splitscreen.SplitScreenController;
import com.android.wm.shell.windowdecor.common.DecorThemeUtil;
import com.android.wm.shell.windowdecor.common.Theme;
import com.android.wm.shell.windowdecor.common.WindowDecorTaskResourceLoader;
import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHost;
import com.android.wm.shell.windowdecor.common.viewhost.WindowDecorViewHostSupplier;
@@ -1083,10 +1085,29 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
        }
        if (isAppHeader
                && DesktopModeStatus.useWindowShadow(/* isFocusedWindow= */ hasGlobalFocus)) {
            if (DesktopExperienceFlags.ENABLE_DYNAMIC_RADIUS_COMPUTATION_BUGFIX.isTrue()) {
            if (DesktopExperienceFlags.ENABLE_FREEFORM_BOX_SHADOWS.isTrue()) {
                // Shadows are same for light and dark theme.
                relayoutParams.mBoxShadowSettingsIds = hasGlobalFocus
                        ? new int[]{R.style.BoxShadowParamsKeyFocused,
                                    R.style.BoxShadowParamsAmbientFocused}
                        : new int[]{R.style.BoxShadowParamsKeyUnfocused,
                                    R.style.BoxShadowParamsAmbientUnfocused};

                final DecorThemeUtil decorThemeUtil = new DecorThemeUtil(context);
                if (decorThemeUtil.getAppTheme(taskInfo) == Theme.DARK) {
                    relayoutParams.mBorderSettingsId = hasGlobalFocus
                            ? R.style.BorderSettingsFocusedDark
                            : R.style.BorderSettingsUnfocusedDark;
                } else  {
                    relayoutParams.mBorderSettingsId = hasGlobalFocus
                            ? R.style.BorderSettingsFocusedLight
                            : R.style.BorderSettingsUnfocusedLight;
                }
            } else if (DesktopExperienceFlags.ENABLE_DYNAMIC_RADIUS_COMPUTATION_BUGFIX.isTrue()) {
                relayoutParams.mShadowRadiusId = hasGlobalFocus
                        ? R.dimen.freeform_decor_shadow_focused_thickness
                        : R.dimen.freeform_decor_shadow_unfocused_thickness;

            } else {
                relayoutParams.mShadowRadius = hasGlobalFocus
                        ? context.getResources().getDimensionPixelSize(
@@ -1095,7 +1116,10 @@ public class DesktopModeWindowDecoration extends WindowDecoration<WindowDecorLin
                                R.dimen.freeform_decor_shadow_unfocused_thickness);
            }
        } else {
            if (DesktopExperienceFlags.ENABLE_DYNAMIC_RADIUS_COMPUTATION_BUGFIX.isTrue()) {
            if (DesktopExperienceFlags.ENABLE_FREEFORM_BOX_SHADOWS.isTrue()) {
                relayoutParams.mBoxShadowSettingsIds = null;
                relayoutParams.mBorderSettingsId = Resources.ID_NULL;
            } else if (DesktopExperienceFlags.ENABLE_DYNAMIC_RADIUS_COMPUTATION_BUGFIX.isTrue()) {
                relayoutParams.mShadowRadiusId = Resources.ID_NULL;
            } else {
                relayoutParams.mShadowRadius = INVALID_SHADOW_RADIUS;
+68 −0
Original line number Diff line number Diff line
@@ -31,11 +31,14 @@ import android.app.WindowConfiguration.WindowingMode;
import android.content.Context;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.graphics.PixelFormat;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.Region;
import android.gui.BorderSettings;
import android.gui.BoxShadowSettings;
import android.os.Binder;
import android.os.Trace;
import android.view.Display;
@@ -55,6 +58,7 @@ import android.window.WindowContainerToken;
import android.window.WindowContainerTransaction;

import com.android.internal.annotations.VisibleForTesting;
import com.android.wm.shell.R;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.desktopmode.DesktopModeEventLogger;
@@ -288,6 +292,49 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
        outResult.mCaptionX = (outResult.mWidth - outResult.mCaptionWidth) / 2;
        outResult.mCaptionY = 0;
        outResult.mCaptionTopPadding = params.mCaptionTopPadding;

        if (params.mBorderSettingsId != Resources.ID_NULL) {
            TypedArray attr = mDecorWindowContext.obtainStyledAttributes(
                    params.mBorderSettingsId, R.styleable.BorderSettings);

            outResult.mBorderSettings = new BorderSettings();
            outResult.mBorderSettings.strokeWidth =
                    attr.getDimension(
                    R.styleable.BorderSettings_borderStrokeWidth, 0f);
            outResult.mBorderSettings.color =
                    attr.getColor(
                    R.styleable.BorderSettings_borderColor, 0);

            attr.recycle();
        }

        if (params.mBoxShadowSettingsIds != null) {
            outResult.mBoxShadowSettings = new BoxShadowSettings();
            outResult.mBoxShadowSettings.boxShadows =
                    new BoxShadowSettings.BoxShadowParams[params.mBoxShadowSettingsIds.length];
            for (int i = 0; i < params.mBoxShadowSettingsIds.length; i++) {
                TypedArray attr = mDecorWindowContext.obtainStyledAttributes(
                        params.mBoxShadowSettingsIds[i], R.styleable.BoxShadowSettings);

                BoxShadowSettings.BoxShadowParams box =
                        new BoxShadowSettings.BoxShadowParams();
                box.blurRadius = attr.getDimension(
                    R.styleable.BoxShadowSettings_boxShadowBlurRadius, 0f);
                box.spreadRadius = attr.getDimension(
                    R.styleable.BoxShadowSettings_boxShadowSpreadRadius, 0f);
                box.offsetX = attr.getDimension(
                    R.styleable.BoxShadowSettings_boxShadowOffsetX, 0f);
                box.offsetY = attr.getDimension(
                    R.styleable.BoxShadowSettings_boxShadowOffsetY, 0f);
                box.color = attr.getColor(
                    R.styleable.BoxShadowSettings_boxShadowColor, 0);

                outResult.mBoxShadowSettings.boxShadows[i] = box;

                attr.recycle();
            }
        }

        if (DesktopExperienceFlags.ENABLE_DYNAMIC_RADIUS_COMPUTATION_BUGFIX.isTrue()) {
            outResult.mCornerRadius = params.mCornerRadiusId == Resources.ID_NULL
                    ? INVALID_CORNER_RADIUS : loadDimensionPixelSize(resources,
@@ -507,6 +554,18 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
                    .setPosition(mTaskSurface, taskPosition.x, taskPosition.y);
        }

        if (outResult.mBorderSettings != null
                && outResult.mBorderSettings.strokeWidth > 0) {
            startT.setBorderSettings(mTaskSurface, outResult.mBorderSettings);
            finishT.setBorderSettings(mTaskSurface, outResult.mBorderSettings);
        }

        if (outResult.mBoxShadowSettings != null
                && outResult.mBoxShadowSettings.boxShadows.length > 0) {
            startT.setBoxShadowSettings(mTaskSurface, outResult.mBoxShadowSettings);
            finishT.setBoxShadowSettings(mTaskSurface, outResult.mBoxShadowSettings);
        }

        if (DesktopExperienceFlags.ENABLE_DYNAMIC_RADIUS_COMPUTATION_BUGFIX.isTrue()) {
            if (outResult.mShadowRadius != INVALID_SHADOW_RADIUS) {
                startT.setShadowRadius(mTaskSurface, outResult.mShadowRadius);
@@ -857,6 +916,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>

        int mShadowRadiusId = Resources.ID_NULL;
        int mCornerRadiusId = Resources.ID_NULL;
        int mBorderSettingsId = Resources.ID_NULL;
        int[] mBoxShadowSettingsIds = null;

        int mCaptionTopPadding;
        boolean mIsCaptionVisible;
@@ -880,6 +941,9 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
            mIsInsetSource = true;
            mInsetSourceFlags = 0;
            mDisplayExclusionRegion.setEmpty();
            mBorderSettingsId = Resources.ID_NULL;
            mBoxShadowSettingsIds = null;

            if (DesktopExperienceFlags.ENABLE_DYNAMIC_RADIUS_COMPUTATION_BUGFIX.isTrue()) {
                mShadowRadiusId = Resources.ID_NULL;
                mCornerRadiusId = Resources.ID_NULL;
@@ -930,6 +994,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
        T mRootView;
        int mCornerRadius;
        int mShadowRadius;
        BorderSettings mBorderSettings;
        BoxShadowSettings mBoxShadowSettings;

        void reset() {
            mWidth = 0;
@@ -941,6 +1007,8 @@ public abstract class WindowDecoration<T extends View & TaskFocusStateConsumer>
            mCaptionTopPadding = 0;
            mCustomizableCaptionRegion.setEmpty();
            mRootView = null;
            mBorderSettings = null;
            mBoxShadowSettings = null;
            if (DesktopExperienceFlags.ENABLE_DYNAMIC_RADIUS_COMPUTATION_BUGFIX.isTrue()) {
                mCornerRadius = INVALID_CORNER_RADIUS;
                mShadowRadius = INVALID_SHADOW_RADIUS;
+16 −0
Original line number Diff line number Diff line
@@ -545,6 +545,22 @@ public class DesktopModeWindowDecorationTests extends ShellTestCase {
        assertThat(relayoutParams.mCornerRadiusId).isEqualTo(Resources.ID_NULL);
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_FREEFORM_BOX_SHADOWS)
    public void updateRelayoutParams_boxShadowsAndOutlineSetForFreeform() {
        final ActivityManager.RunningTaskInfo taskInfo = createTaskInfo(/* visible= */ true);
        taskInfo.configuration.windowConfiguration.setWindowingMode(WINDOWING_MODE_FREEFORM);
        RelayoutParams relayoutParams = new RelayoutParams();

        updateRelayoutParams(relayoutParams, taskInfo);

        assertThat(relayoutParams.mBoxShadowSettingsIds.length).isGreaterThan(0);
        for (int i = 0; i < relayoutParams.mBoxShadowSettingsIds.length; i++) {
            assertThat(relayoutParams.mBoxShadowSettingsIds[i]).isNotEqualTo(Resources.ID_NULL);
        }
        assertThat(relayoutParams.mBorderSettingsId).isNotEqualTo(Resources.ID_NULL);
    }

    @Test
    @EnableFlags(Flags.FLAG_ENABLE_APP_HEADER_WITH_TASK_DENSITY)
    public void updateRelayoutParams_appHeader_usesTaskDensity() {
Loading