Loading core/java/android/view/InsetsState.java +36 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; } Loading Loading @@ -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]; Loading @@ -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++) { Loading @@ -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--) { Loading Loading @@ -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]; Loading Loading @@ -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; } Loading @@ -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) { Loading @@ -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); } Loading @@ -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); } Loading @@ -914,6 +945,7 @@ public class InsetsState implements Parcelable { + "mDisplayFrame=" + mDisplayFrame + ", mDisplayCutout=" + mDisplayCutout + ", mRoundedCorners=" + mRoundedCorners + " mRoundedCornerFrame=" + mRoundedCornerFrame + ", mPrivacyIndicatorBounds=" + mPrivacyIndicatorBounds + ", mSources= { " + joiner + " }"; Loading core/java/android/view/RoundedCorners.java +55 −8 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. * Loading @@ -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: Loading @@ -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); } /** Loading core/java/android/view/WindowManager.java +22 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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); Loading Loading @@ -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]; Loading Loading @@ -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(); Loading Loading @@ -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="); Loading services/core/java/com/android/server/wm/DisplayPolicy.java +24 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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()); } Loading Loading @@ -1250,6 +1266,10 @@ public class DisplayPolicy { if (mLastFocusedWindow == win) { mLastFocusedWindow = null; } if (mRoundedCornerWindow == win) { mRoundedCornerWindow = null; } mInsetsSourceWindowsExceptIme.remove(win); } Loading Loading @@ -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 Loading services/core/java/com/android/server/wm/InsetsPolicy.java +33 −3 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); } /** Loading Loading @@ -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); Loading Loading
core/java/android/view/InsetsState.java +36 −4 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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; Loading Loading @@ -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; } Loading Loading @@ -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]; Loading @@ -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++) { Loading @@ -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--) { Loading Loading @@ -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]; Loading Loading @@ -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; } Loading @@ -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) { Loading @@ -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); } Loading @@ -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); } Loading @@ -914,6 +945,7 @@ public class InsetsState implements Parcelable { + "mDisplayFrame=" + mDisplayFrame + ", mDisplayCutout=" + mDisplayCutout + ", mRoundedCorners=" + mRoundedCorners + " mRoundedCornerFrame=" + mRoundedCornerFrame + ", mPrivacyIndicatorBounds=" + mPrivacyIndicatorBounds + ", mSources= { " + joiner + " }"; Loading
core/java/android/view/RoundedCorners.java +55 −8 Original line number Diff line number Diff line Loading @@ -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; Loading Loading @@ -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. * Loading @@ -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: Loading @@ -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); } /** Loading
core/java/android/view/WindowManager.java +22 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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); Loading Loading @@ -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]; Loading Loading @@ -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(); Loading Loading @@ -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="); Loading
services/core/java/com/android/server/wm/DisplayPolicy.java +24 −0 Original line number Diff line number Diff line Loading @@ -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. Loading Loading @@ -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()); } Loading Loading @@ -1250,6 +1266,10 @@ public class DisplayPolicy { if (mLastFocusedWindow == win) { mLastFocusedWindow = null; } if (mRoundedCornerWindow == win) { mRoundedCornerWindow = null; } mInsetsSourceWindowsExceptIme.remove(win); } Loading Loading @@ -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 Loading
services/core/java/com/android/server/wm/InsetsPolicy.java +33 −3 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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; Loading Loading @@ -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); } /** Loading Loading @@ -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); Loading