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

Commit 1c3c9fa8 authored by Shawn Lin's avatar Shawn Lin Committed by Android (Google) Code Review
Browse files

Merge "Add mechanism for customization of rounded corner insets"

parents f86b4b49 3fc90a72
Loading
Loading
Loading
Loading
+36 −4
Original line number Diff line number Diff line
@@ -168,6 +168,16 @@ public class InsetsState implements Parcelable {
    private final DisplayCutout.ParcelableWrapper mDisplayCutout =
            new DisplayCutout.ParcelableWrapper();

    /**
     * The frame that rounded corners are relative to.
     *
     * There are 2 cases that will draw fake rounded corners:
     *   1. In split-screen mode
     *   2. Devices with a task bar
     * We need to report these fake rounded corners to apps by re-calculating based on this frame.
     */
    private final Rect mRoundedCornerFrame = new Rect();

    /** The rounded corners on the display */
    private RoundedCorners mRoundedCorners = RoundedCorners.NO_ROUNDED_CORNERS;

@@ -274,12 +284,17 @@ public class InsetsState implements Parcelable {
    }

    private RoundedCorners calculateRelativeRoundedCorners(Rect frame) {
        if (mDisplayFrame.equals(frame)) {
            return mRoundedCorners;
        }
        if (frame == null) {
            return RoundedCorners.NO_ROUNDED_CORNERS;
        }
        // If mRoundedCornerFrame is set, we should calculate the new RoundedCorners based on this
        // frame. It's used for split-screen mode and devices with a task bar.
        if (!mRoundedCornerFrame.isEmpty() && !mRoundedCornerFrame.equals(mDisplayFrame)) {
            return mRoundedCorners.insetWithFrame(frame, mRoundedCornerFrame);
        }
        if (mDisplayFrame.equals(frame)) {
            return mRoundedCorners;
        }
        final int insetLeft = frame.left - mDisplayFrame.left;
        final int insetTop = frame.top - mDisplayFrame.top;
        final int insetRight = mDisplayFrame.right - frame.right;
@@ -530,6 +545,15 @@ public class InsetsState implements Parcelable {
        return mRoundedCorners;
    }

    /**
     * Set the frame that will be used to calculate the rounded corners.
     *
     * @see #mRoundedCornerFrame
     */
    public void setRoundedCornerFrame(Rect frame) {
        mRoundedCornerFrame.set(frame);
    }

    public void setPrivacyIndicatorBounds(PrivacyIndicatorBounds bounds) {
        mPrivacyIndicatorBounds = bounds;
    }
@@ -575,6 +599,7 @@ public class InsetsState implements Parcelable {
        mDisplayFrame.scale(scale);
        mDisplayCutout.scale(scale);
        mRoundedCorners = mRoundedCorners.scale(scale);
        mRoundedCornerFrame.scale(scale);
        mPrivacyIndicatorBounds = mPrivacyIndicatorBounds.scale(scale);
        for (int i = 0; i < SIZE; i++) {
            final InsetsSource source = mSources[i];
@@ -596,6 +621,7 @@ public class InsetsState implements Parcelable {
        mDisplayFrame.set(other.mDisplayFrame);
        mDisplayCutout.set(other.mDisplayCutout);
        mRoundedCorners = other.getRoundedCorners();
        mRoundedCornerFrame.set(other.mRoundedCornerFrame);
        mPrivacyIndicatorBounds = other.getPrivacyIndicatorBounds();
        if (copySources) {
            for (int i = 0; i < SIZE; i++) {
@@ -620,6 +646,7 @@ public class InsetsState implements Parcelable {
        mDisplayFrame.set(other.mDisplayFrame);
        mDisplayCutout.set(other.mDisplayCutout);
        mRoundedCorners = other.getRoundedCorners();
        mRoundedCornerFrame.set(other.mRoundedCornerFrame);
        mPrivacyIndicatorBounds = other.getPrivacyIndicatorBounds();
        final ArraySet<Integer> t = toInternalType(types);
        for (int i = t.size() - 1; i >= 0; i--) {
@@ -740,6 +767,7 @@ public class InsetsState implements Parcelable {
        pw.println(newPrefix + "mDisplayFrame=" + mDisplayFrame);
        pw.println(newPrefix + "mDisplayCutout=" + mDisplayCutout.get());
        pw.println(newPrefix + "mRoundedCorners=" + mRoundedCorners);
        pw.println(newPrefix + "mRoundedCornerFrame=" + mRoundedCornerFrame);
        pw.println(newPrefix + "mPrivacyIndicatorBounds=" + mPrivacyIndicatorBounds);
        for (int i = 0; i < SIZE; i++) {
            InsetsSource source = mSources[i];
@@ -836,6 +864,7 @@ public class InsetsState implements Parcelable {
        if (!mDisplayFrame.equals(state.mDisplayFrame)
                || !mDisplayCutout.equals(state.mDisplayCutout)
                || !mRoundedCorners.equals(state.mRoundedCorners)
                || !mRoundedCornerFrame.equals(state.mRoundedCornerFrame)
                || !mPrivacyIndicatorBounds.equals(state.mPrivacyIndicatorBounds)) {
            return false;
        }
@@ -861,7 +890,7 @@ public class InsetsState implements Parcelable {
    @Override
    public int hashCode() {
        return Objects.hash(mDisplayFrame, mDisplayCutout, Arrays.hashCode(mSources),
                mRoundedCorners, mPrivacyIndicatorBounds);
                mRoundedCorners, mPrivacyIndicatorBounds, mRoundedCornerFrame);
    }

    public InsetsState(Parcel in) {
@@ -879,6 +908,7 @@ public class InsetsState implements Parcelable {
        mDisplayCutout.writeToParcel(dest, flags);
        dest.writeTypedArray(mSources, 0 /* parcelableFlags */);
        dest.writeTypedObject(mRoundedCorners, flags);
        mRoundedCornerFrame.writeToParcel(dest, flags);
        dest.writeTypedObject(mPrivacyIndicatorBounds, flags);
    }

@@ -898,6 +928,7 @@ public class InsetsState implements Parcelable {
        mDisplayCutout.readFromParcel(in);
        in.readTypedArray(mSources, InsetsSource.CREATOR);
        mRoundedCorners = in.readTypedObject(RoundedCorners.CREATOR);
        mRoundedCornerFrame.readFromParcel(in);
        mPrivacyIndicatorBounds = in.readTypedObject(PrivacyIndicatorBounds.CREATOR);
    }

@@ -914,6 +945,7 @@ public class InsetsState implements Parcelable {
                + "mDisplayFrame=" + mDisplayFrame
                + ", mDisplayCutout=" + mDisplayCutout
                + ", mRoundedCorners=" + mRoundedCorners
                + "  mRoundedCornerFrame=" + mRoundedCornerFrame
                + ", mPrivacyIndicatorBounds=" + mPrivacyIndicatorBounds
                + ", mSources= { " + joiner
                + " }";
+55 −8
Original line number Diff line number Diff line
@@ -28,7 +28,7 @@ import android.annotation.NonNull;
import android.annotation.Nullable;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Point;
import android.graphics.Rect;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.DisplayUtils;
@@ -319,6 +319,53 @@ public class RoundedCorners implements Parcelable {
        return isRound;
    }

    /**
     * Insets the reference frame of the rounded corners.
     *
     * @param frame the frame of a window or any rectangle bounds
     * @param roundedCornerFrame the frame that used to calculate relative {@link RoundedCorner}
     * @return a copy of this instance which has been inset
     */
    public RoundedCorners insetWithFrame(Rect frame, Rect roundedCornerFrame) {
        int insetLeft = frame.left - roundedCornerFrame.left;
        int insetTop = frame.top - roundedCornerFrame.top;
        int insetRight = roundedCornerFrame.right - frame.right;
        int insetBottom = roundedCornerFrame.bottom - frame.bottom;
        final RoundedCorner[] roundedCorners = new RoundedCorner[ROUNDED_CORNER_POSITION_LENGTH];
        int centerX, centerY;
        for (int i = 0; i < ROUNDED_CORNER_POSITION_LENGTH; i++) {
            if (mRoundedCorners[i].isEmpty()) {
                roundedCorners[i] = new RoundedCorner(i);
                continue;
            }
            final int radius = mRoundedCorners[i].getRadius();
            switch (i) {
                case POSITION_TOP_LEFT:
                    centerX = radius;
                    centerY = radius;
                    break;
                case POSITION_TOP_RIGHT:
                    centerX = roundedCornerFrame.width() - radius;
                    centerY = radius;
                    break;
                case POSITION_BOTTOM_RIGHT:
                    centerX = roundedCornerFrame.width() - radius;
                    centerY = roundedCornerFrame.height() - radius;
                    break;
                case POSITION_BOTTOM_LEFT:
                    centerX = radius;
                    centerY = roundedCornerFrame.height() - radius;
                    break;
                default:
                    throw new IllegalArgumentException(
                            "The position is not one of the RoundedCornerPosition =" + i);
            }
            roundedCorners[i] = insetRoundedCorner(i, radius, centerX, centerY, insetLeft, insetTop,
                    insetRight, insetBottom);
        }
        return new RoundedCorners(roundedCorners);
    }

    /**
     * Insets the reference frame of the rounded corners.
     *
@@ -327,19 +374,19 @@ public class RoundedCorners implements Parcelable {
    public RoundedCorners inset(int insetLeft, int insetTop, int insetRight, int insetBottom) {
        final RoundedCorner[] roundedCorners = new RoundedCorner[ROUNDED_CORNER_POSITION_LENGTH];
        for (int i = 0; i < ROUNDED_CORNER_POSITION_LENGTH; i++) {
            roundedCorners[i] = insetRoundedCorner(i, insetLeft, insetTop, insetRight, insetBottom);
            roundedCorners[i] = insetRoundedCorner(i, mRoundedCorners[i].getRadius(),
                    mRoundedCorners[i].getCenter().x, mRoundedCorners[i].getCenter().y, insetLeft,
                    insetTop, insetRight, insetBottom);
        }
        return new RoundedCorners(roundedCorners);
    }

    private RoundedCorner insetRoundedCorner(@Position int position, int insetLeft,
            int insetTop, int insetRight, int insetBottom) {
    private RoundedCorner insetRoundedCorner(@Position int position, int radius, int centerX,
            int centerY, int insetLeft, int insetTop, int insetRight, int insetBottom) {
        if (mRoundedCorners[position].isEmpty()) {
            return new RoundedCorner(position);
        }

        final int radius = mRoundedCorners[position].getRadius();
        final Point center = mRoundedCorners[position].getCenter();
        boolean hasRoundedCorner;
        switch (position) {
            case POSITION_TOP_LEFT:
@@ -360,8 +407,8 @@ public class RoundedCorners implements Parcelable {
        }
        return new RoundedCorner(
                position, radius,
                hasRoundedCorner ? center.x - insetLeft : 0,
                hasRoundedCorner ? center.y - insetTop : 0);
                hasRoundedCorner ? centerX - insetLeft : 0,
                hasRoundedCorner ? centerY - insetTop : 0);
    }

    /**
+22 −0
Original line number Diff line number Diff line
@@ -3573,6 +3573,17 @@ public interface WindowManager extends ViewManager {
         */
        public Insets providedInternalImeInsets = Insets.NONE;

        /**
         * If specified, the frame that used to calculate relative {@link RoundedCorner} will be
         * the window frame of this window minus the insets that this window provides.
         *
         * Task bar will draw fake rounded corners above itself, so we need this insets to calculate
         * correct rounded corners for this window.
         *
         * @hide
         */
        public boolean insetsRoundedCornerFrame = false;

        /**
         * {@link LayoutParams} to be applied to the window when layout with a assigned rotation.
         * This will make layout during rotation change smoothly.
@@ -3948,6 +3959,7 @@ public interface WindowManager extends ViewManager {
            }
            providedInternalInsets.writeToParcel(out, 0 /* parcelableFlags */);
            providedInternalImeInsets.writeToParcel(out, 0 /* parcelableFlags */);
            out.writeBoolean(insetsRoundedCornerFrame);
            if (paramsForRotation != null) {
                checkNonRecursiveParams();
                out.writeInt(paramsForRotation.length);
@@ -4028,6 +4040,7 @@ public interface WindowManager extends ViewManager {
            }
            providedInternalInsets = Insets.CREATOR.createFromParcel(in);
            providedInternalImeInsets = Insets.CREATOR.createFromParcel(in);
            insetsRoundedCornerFrame = in.readBoolean();
            int paramsForRotationLength = in.readInt();
            if (paramsForRotationLength > 0) {
                paramsForRotation = new LayoutParams[paramsForRotationLength];
@@ -4339,6 +4352,11 @@ public interface WindowManager extends ViewManager {
                changes |= LAYOUT_CHANGED;
            }

            if (insetsRoundedCornerFrame != o.insetsRoundedCornerFrame) {
                insetsRoundedCornerFrame = o.insetsRoundedCornerFrame;
                changes |= LAYOUT_CHANGED;
            }

            if (!Arrays.equals(paramsForRotation, o.paramsForRotation)) {
                paramsForRotation = o.paramsForRotation;
                checkNonRecursiveParams();
@@ -4548,6 +4566,10 @@ public interface WindowManager extends ViewManager {
                sb.append(" providedInternalImeInsets=");
                sb.append(providedInternalImeInsets);
            }
            if (insetsRoundedCornerFrame) {
                sb.append(" insetsRoundedCornerFrame=");
                sb.append(insetsRoundedCornerFrame);
            }
            if (paramsForRotation != null && paramsForRotation.length != 0) {
                sb.append(System.lineSeparator());
                sb.append(prefix).append("  paramsForRotation=");
+24 −0
Original line number Diff line number Diff line
@@ -302,6 +302,10 @@ public class DisplayPolicy {
    // needs to be opaque.
    private WindowState mNavBarBackgroundWindow;

    // The window that draws fake rounded corners and should provide insets to calculate the correct
    // rounded corner insets.
    private WindowState mRoundedCornerWindow;

    /**
     * Windows to determine the color of status bar. See {@link #mNavBarColorWindowCandidate} for
     * the conditions of being candidate window.
@@ -927,6 +931,18 @@ public class DisplayPolicy {
            mExtraNavBarAltPosition = getAltBarPosition(attrs);
        }

        if (attrs.insetsRoundedCornerFrame) {
            // Currently, only support one rounded corner window which is the TaskBar.
            if (mRoundedCornerWindow != null && mRoundedCornerWindow != win) {
                throw new IllegalArgumentException("Found multiple rounded corner window :"
                        + " current = " + mRoundedCornerWindow
                        + " new = " + win);
            }
            mRoundedCornerWindow = win;
        } else if (mRoundedCornerWindow == win) {
            mRoundedCornerWindow = null;
        }

        attrs.flags = sanitizeFlagSlippery(attrs.flags, attrs.privateFlags, win.getName());
    }

@@ -1250,6 +1266,10 @@ public class DisplayPolicy {
        if (mLastFocusedWindow == win) {
            mLastFocusedWindow = null;
        }
        if (mRoundedCornerWindow == win) {
            mRoundedCornerWindow = null;
        }

        mInsetsSourceWindowsExceptIme.remove(win);
    }

@@ -1280,6 +1300,10 @@ public class DisplayPolicy {
        return mNavigationBar != null ? mNavigationBar : mNavigationBarAlt;
    }

    WindowState getRoundedCornerWindow() {
        return mRoundedCornerWindow;
    }

    /**
     * Control the animation to run when a window's state changes.  Return a positive number to
     * force the animation to a specific resource ID, {@link #ANIMATION_STYLEABLE} to use the
+33 −3
Original line number Diff line number Diff line
@@ -33,6 +33,8 @@ import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_STATUS_FORCE_
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.app.StatusBarManager;
import android.graphics.Insets;
import android.graphics.Rect;
import android.util.IntArray;
import android.util.SparseArray;
import android.view.InsetsAnimationControlCallbacks;
@@ -50,7 +52,6 @@ import android.view.WindowInsets.Type;
import android.view.WindowInsetsAnimation;
import android.view.WindowInsetsAnimation.Bounds;
import android.view.WindowInsetsAnimationControlListener;
import android.view.WindowInsetsAnimationController;
import android.view.WindowManager;

import com.android.internal.R;
@@ -220,8 +221,9 @@ class InsetsPolicy {
     */
    InsetsState getInsetsForWindow(WindowState target) {
        final InsetsState originalState = mStateController.getInsetsForWindow(target);
        final InsetsState state = adjustVisibilityForTransientTypes(originalState);
        return adjustVisibilityForIme(target, state, state == originalState);
        InsetsState state = adjustVisibilityForTransientTypes(originalState);
        state = adjustVisibilityForIme(target, state, state == originalState);
        return adjustInsetsForRoundedCorners(target, state, state == originalState);
    }

    /**
@@ -286,6 +288,34 @@ class InsetsPolicy {
        return originalState;
    }

    private InsetsState adjustInsetsForRoundedCorners(WindowState w, InsetsState originalState,
            boolean copyState) {
        final WindowState roundedCornerWindow = mPolicy.getRoundedCornerWindow();
        final Task task = w.getTask();
        final boolean isInSplitScreenMode = task != null && task.inMultiWindowMode()
                && task.getRootTask() != null
                && task.getRootTask().getAdjacentTaskFragment() != null;
        if (task != null && !task.getWindowConfiguration().tasksAreFloating()
                && (roundedCornerWindow != null || isInSplitScreenMode)) {
            // Instead of using display frame to calculating rounded corner, for the fake rounded
            // corners drawn by divider bar or task bar, we need to re-calculate rounded corners
            // based on task bounds and if the task bounds is intersected with task bar, we should
            // exclude the intersected part.
            final Rect roundedCornerFrame = new Rect(task.getBounds());
            if (roundedCornerWindow != null
                    && roundedCornerWindow.getControllableInsetProvider() != null) {
                final InsetsSource source =
                        roundedCornerWindow.getControllableInsetProvider().getSource();
                final Insets insets = source.calculateInsets(roundedCornerFrame, false);
                roundedCornerFrame.inset(insets);
            }
            final InsetsState state = copyState ? new InsetsState(originalState) : originalState;
            state.setRoundedCornerFrame(roundedCornerFrame);
            return state;
        }
        return originalState;
    }

    void onInsetsModified(InsetsControlTarget caller) {
        mStateController.onInsetsModified(caller);
        checkAbortTransient(caller);