413 lines
14 KiB
Java
413 lines
14 KiB
Java
![]() |
/*
|
||
|
* Copyright (C) 2022 The Android Open Source Project
|
||
|
*
|
||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||
|
* you may not use this file except in compliance with the License.
|
||
|
* You may obtain a copy of the License at
|
||
|
*
|
||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||
|
*
|
||
|
* Unless required by applicable law or agreed to in writing, software
|
||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||
|
* See the License for the specific language governing permissions and
|
||
|
* limitations under the License.
|
||
|
*/
|
||
|
|
||
|
package android.view;
|
||
|
|
||
|
import android.annotation.IntRange;
|
||
|
import android.annotation.NonNull;
|
||
|
import android.annotation.Nullable;
|
||
|
import android.graphics.Insets;
|
||
|
import android.graphics.Rect;
|
||
|
import android.os.IBinder;
|
||
|
import android.os.Parcel;
|
||
|
import android.os.Parcelable;
|
||
|
import android.view.InsetsSource.Flags;
|
||
|
import android.view.WindowInsets.Type.InsetsType;
|
||
|
|
||
|
import java.util.Arrays;
|
||
|
import java.util.Objects;
|
||
|
|
||
|
/**
|
||
|
* Insets provided by a window.
|
||
|
*
|
||
|
* The insets frame will by default as the window frame size. If the providers are set, the
|
||
|
* calculation result based on the source size will be used as the insets frame.
|
||
|
*
|
||
|
* The InsetsFrameProvider should be self-contained. Nothing describing the window itself, such as
|
||
|
* contentInsets, visibleInsets, etc. won't affect the insets providing to other windows when this
|
||
|
* is set.
|
||
|
* @hide
|
||
|
*/
|
||
|
public class InsetsFrameProvider implements Parcelable {
|
||
|
|
||
|
/**
|
||
|
* Uses the display frame as the source.
|
||
|
*/
|
||
|
public static final int SOURCE_DISPLAY = 0;
|
||
|
|
||
|
/**
|
||
|
* Uses the window bounds as the source.
|
||
|
*/
|
||
|
public static final int SOURCE_CONTAINER_BOUNDS = 1;
|
||
|
|
||
|
/**
|
||
|
* Uses the window frame as the source.
|
||
|
*/
|
||
|
public static final int SOURCE_FRAME = 2;
|
||
|
|
||
|
/**
|
||
|
* Uses {@link #mArbitraryRectangle} as the source.
|
||
|
*/
|
||
|
public static final int SOURCE_ARBITRARY_RECTANGLE = 3;
|
||
|
|
||
|
private final int mId;
|
||
|
|
||
|
/**
|
||
|
* The selection of the starting rectangle to be converted into source frame.
|
||
|
*/
|
||
|
private int mSource = SOURCE_FRAME;
|
||
|
|
||
|
/**
|
||
|
* This is used as the source frame only if SOURCE_ARBITRARY_RECTANGLE is applied.
|
||
|
*/
|
||
|
private Rect mArbitraryRectangle;
|
||
|
|
||
|
/**
|
||
|
* Modifies the starting rectangle selected by {@link #mSource}.
|
||
|
*
|
||
|
* For example, when the given source frame is (0, 0) - (100, 200), and the insetsSize is null,
|
||
|
* the source frame will be directly used as the final insets frame. If the insetsSize is set to
|
||
|
* (0, 0, 0, 50) instead, the insets frame will be a frame starting from the bottom side of the
|
||
|
* source frame with height of 50, i.e., (0, 150) - (100, 200).
|
||
|
*/
|
||
|
private Insets mInsetsSize = null;
|
||
|
|
||
|
/**
|
||
|
* Various behavioral options/flags. Default is none.
|
||
|
*
|
||
|
* @see Flags
|
||
|
*/
|
||
|
private @Flags int mFlags;
|
||
|
|
||
|
/**
|
||
|
* If null, the size set in insetsSize will be applied to all window types. If it contains
|
||
|
* element of some types, the insets reported to the window with that types will be overridden.
|
||
|
*/
|
||
|
private InsetsSizeOverride[] mInsetsSizeOverrides = null;
|
||
|
|
||
|
/**
|
||
|
* This field, if set, is indicating the insets needs to be at least the given size inside the
|
||
|
* display cutout safe area. This will be compared to the insets size calculated based on other
|
||
|
* attributes, and will be applied when this is larger. This is independent of the
|
||
|
* PRIVATE_FLAG_LAYOUT_SIZE_EXTENDED_BY_CUTOUT in LayoutParams, as this is not going to change
|
||
|
* the layout of the window, but only change the insets frame. This can be applied to insets
|
||
|
* calculated based on all three source frames.
|
||
|
*
|
||
|
* Be cautious, this will not be in effect for the window types whose insets size is overridden.
|
||
|
*/
|
||
|
private Insets mMinimalInsetsSizeInDisplayCutoutSafe = null;
|
||
|
|
||
|
/**
|
||
|
* Indicates the bounding rectangles within the provided insets frame, in relative coordinates
|
||
|
* to the source frame.
|
||
|
*/
|
||
|
private Rect[] mBoundingRects = null;
|
||
|
|
||
|
/**
|
||
|
* Creates an InsetsFrameProvider which describes what frame an insets source should have.
|
||
|
*
|
||
|
* @param owner the owner of this provider. We might have multiple sources with the same type on
|
||
|
* a display, this is used to identify them.
|
||
|
* @param index the index of this provider. An owner might provide multiple sources with the
|
||
|
* same type, this is used to identify them.
|
||
|
* The value must be in a range of [0, 2047].
|
||
|
* @param type the {@link InsetsType}.
|
||
|
* @see InsetsSource#createId(Object, int, int)
|
||
|
*/
|
||
|
public InsetsFrameProvider(Object owner, @IntRange(from = 0, to = 2047) int index,
|
||
|
@InsetsType int type) {
|
||
|
mId = InsetsSource.createId(owner, index, type);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns an unique integer which identifies the insets source.
|
||
|
*/
|
||
|
public int getId() {
|
||
|
return mId;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the index specified in {@link #InsetsFrameProvider(IBinder, int, int)}.
|
||
|
*/
|
||
|
public int getIndex() {
|
||
|
return InsetsSource.getIndex(mId);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the {@link InsetsType} specified in {@link #InsetsFrameProvider(IBinder, int, int)}.
|
||
|
*/
|
||
|
public int getType() {
|
||
|
return InsetsSource.getType(mId);
|
||
|
}
|
||
|
|
||
|
public InsetsFrameProvider setSource(int source) {
|
||
|
mSource = source;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
public int getSource() {
|
||
|
return mSource;
|
||
|
}
|
||
|
|
||
|
public InsetsFrameProvider setFlags(@Flags int flags, @Flags int mask) {
|
||
|
mFlags = (mFlags & ~mask) | (flags & mask);
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
public @Flags int getFlags() {
|
||
|
return mFlags;
|
||
|
}
|
||
|
|
||
|
public boolean hasFlags(@Flags int mask) {
|
||
|
return (mFlags & mask) == mask;
|
||
|
}
|
||
|
|
||
|
public InsetsFrameProvider setInsetsSize(Insets insetsSize) {
|
||
|
mInsetsSize = insetsSize;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
public Insets getInsetsSize() {
|
||
|
return mInsetsSize;
|
||
|
}
|
||
|
|
||
|
public InsetsFrameProvider setArbitraryRectangle(Rect rect) {
|
||
|
mArbitraryRectangle = new Rect(rect);
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
public Rect getArbitraryRectangle() {
|
||
|
return mArbitraryRectangle;
|
||
|
}
|
||
|
|
||
|
public InsetsFrameProvider setInsetsSizeOverrides(InsetsSizeOverride[] insetsSizeOverrides) {
|
||
|
mInsetsSizeOverrides = insetsSizeOverrides;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
public InsetsSizeOverride[] getInsetsSizeOverrides() {
|
||
|
return mInsetsSizeOverrides;
|
||
|
}
|
||
|
|
||
|
public InsetsFrameProvider setMinimalInsetsSizeInDisplayCutoutSafe(
|
||
|
Insets minimalInsetsSizeInDisplayCutoutSafe) {
|
||
|
mMinimalInsetsSizeInDisplayCutoutSafe = minimalInsetsSizeInDisplayCutoutSafe;
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
public Insets getMinimalInsetsSizeInDisplayCutoutSafe() {
|
||
|
return mMinimalInsetsSizeInDisplayCutoutSafe;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Sets the bounding rectangles within and relative to the source frame.
|
||
|
*/
|
||
|
public InsetsFrameProvider setBoundingRects(@Nullable Rect[] boundingRects) {
|
||
|
mBoundingRects = boundingRects == null ? null : boundingRects.clone();
|
||
|
return this;
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Returns the arbitrary bounding rects, or null if none were set.
|
||
|
*/
|
||
|
@Nullable
|
||
|
public Rect[] getBoundingRects() {
|
||
|
return mBoundingRects;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int describeContents() {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public String toString() {
|
||
|
final StringBuilder sb = new StringBuilder("InsetsFrameProvider: {");
|
||
|
sb.append("id=#").append(Integer.toHexString(mId));
|
||
|
sb.append(", index=").append(getIndex());
|
||
|
sb.append(", type=").append(WindowInsets.Type.toString(getType()));
|
||
|
sb.append(", source=").append(sourceToString(mSource));
|
||
|
sb.append(", flags=[").append(InsetsSource.flagsToString(mFlags)).append("]");
|
||
|
if (mInsetsSize != null) {
|
||
|
sb.append(", insetsSize=").append(mInsetsSize);
|
||
|
}
|
||
|
if (mInsetsSizeOverrides != null) {
|
||
|
sb.append(", insetsSizeOverrides=").append(Arrays.toString(mInsetsSizeOverrides));
|
||
|
}
|
||
|
if (mArbitraryRectangle != null) {
|
||
|
sb.append(", mArbitraryRectangle=").append(mArbitraryRectangle.toShortString());
|
||
|
}
|
||
|
if (mMinimalInsetsSizeInDisplayCutoutSafe != null) {
|
||
|
sb.append(", mMinimalInsetsSizeInDisplayCutoutSafe=")
|
||
|
.append(mMinimalInsetsSizeInDisplayCutoutSafe);
|
||
|
}
|
||
|
if (mBoundingRects != null) {
|
||
|
sb.append(", mBoundingRects=").append(Arrays.toString(mBoundingRects));
|
||
|
}
|
||
|
sb.append("}");
|
||
|
return sb.toString();
|
||
|
}
|
||
|
|
||
|
private static String sourceToString(int source) {
|
||
|
switch (source) {
|
||
|
case SOURCE_DISPLAY:
|
||
|
return "DISPLAY";
|
||
|
case SOURCE_CONTAINER_BOUNDS:
|
||
|
return "CONTAINER_BOUNDS";
|
||
|
case SOURCE_FRAME:
|
||
|
return "FRAME";
|
||
|
case SOURCE_ARBITRARY_RECTANGLE:
|
||
|
return "ARBITRARY_RECTANGLE";
|
||
|
}
|
||
|
return "UNDEFINED";
|
||
|
}
|
||
|
|
||
|
public InsetsFrameProvider(Parcel in) {
|
||
|
mId = in.readInt();
|
||
|
mSource = in.readInt();
|
||
|
mFlags = in.readInt();
|
||
|
mInsetsSize = in.readTypedObject(Insets.CREATOR);
|
||
|
mInsetsSizeOverrides = in.createTypedArray(InsetsSizeOverride.CREATOR);
|
||
|
mArbitraryRectangle = in.readTypedObject(Rect.CREATOR);
|
||
|
mMinimalInsetsSizeInDisplayCutoutSafe = in.readTypedObject(Insets.CREATOR);
|
||
|
mBoundingRects = in.createTypedArray(Rect.CREATOR);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void writeToParcel(Parcel out, int flags) {
|
||
|
out.writeInt(mId);
|
||
|
out.writeInt(mSource);
|
||
|
out.writeInt(mFlags);
|
||
|
out.writeTypedObject(mInsetsSize, flags);
|
||
|
out.writeTypedArray(mInsetsSizeOverrides, flags);
|
||
|
out.writeTypedObject(mArbitraryRectangle, flags);
|
||
|
out.writeTypedObject(mMinimalInsetsSizeInDisplayCutoutSafe, flags);
|
||
|
out.writeTypedArray(mBoundingRects, flags);
|
||
|
}
|
||
|
|
||
|
public boolean idEquals(InsetsFrameProvider o) {
|
||
|
return mId == o.mId;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public boolean equals(Object o) {
|
||
|
if (this == o) {
|
||
|
return true;
|
||
|
}
|
||
|
if (o == null || getClass() != o.getClass()) {
|
||
|
return false;
|
||
|
}
|
||
|
final InsetsFrameProvider other = (InsetsFrameProvider) o;
|
||
|
return mId == other.mId && mSource == other.mSource && mFlags == other.mFlags
|
||
|
&& Objects.equals(mInsetsSize, other.mInsetsSize)
|
||
|
&& Arrays.equals(mInsetsSizeOverrides, other.mInsetsSizeOverrides)
|
||
|
&& Objects.equals(mArbitraryRectangle, other.mArbitraryRectangle)
|
||
|
&& Objects.equals(mMinimalInsetsSizeInDisplayCutoutSafe,
|
||
|
other.mMinimalInsetsSizeInDisplayCutoutSafe)
|
||
|
&& Arrays.equals(mBoundingRects, other.mBoundingRects);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int hashCode() {
|
||
|
return Objects.hash(mId, mSource, mFlags, mInsetsSize,
|
||
|
Arrays.hashCode(mInsetsSizeOverrides), mArbitraryRectangle,
|
||
|
mMinimalInsetsSizeInDisplayCutoutSafe, Arrays.hashCode(mBoundingRects));
|
||
|
}
|
||
|
|
||
|
public static final @NonNull Parcelable.Creator<InsetsFrameProvider> CREATOR =
|
||
|
new Parcelable.Creator<>() {
|
||
|
@Override
|
||
|
public InsetsFrameProvider createFromParcel(Parcel in) {
|
||
|
return new InsetsFrameProvider(in);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public InsetsFrameProvider[] newArray(int size) {
|
||
|
return new InsetsFrameProvider[size];
|
||
|
}
|
||
|
};
|
||
|
|
||
|
/**
|
||
|
* Class to describe the insets size to be provided to window with specific window type. If not
|
||
|
* used, same insets size will be sent as instructed in the insetsSize and source.
|
||
|
*
|
||
|
* If the insetsSize of given type is set to {@code null}, the insets source frame will be used
|
||
|
* directly for that window type.
|
||
|
*/
|
||
|
public static class InsetsSizeOverride implements Parcelable {
|
||
|
|
||
|
private final int mWindowType;
|
||
|
private final Insets mInsetsSize;
|
||
|
|
||
|
protected InsetsSizeOverride(Parcel in) {
|
||
|
mWindowType = in.readInt();
|
||
|
mInsetsSize = in.readTypedObject(Insets.CREATOR);
|
||
|
}
|
||
|
|
||
|
public InsetsSizeOverride(int windowType, Insets insetsSize) {
|
||
|
mWindowType = windowType;
|
||
|
mInsetsSize = insetsSize;
|
||
|
}
|
||
|
public int getWindowType() {
|
||
|
return mWindowType;
|
||
|
}
|
||
|
|
||
|
public Insets getInsetsSize() {
|
||
|
return mInsetsSize;
|
||
|
}
|
||
|
|
||
|
public static final Creator<InsetsSizeOverride> CREATOR = new Creator<>() {
|
||
|
@Override
|
||
|
public InsetsSizeOverride createFromParcel(Parcel in) {
|
||
|
return new InsetsSizeOverride(in);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public InsetsSizeOverride[] newArray(int size) {
|
||
|
return new InsetsSizeOverride[size];
|
||
|
}
|
||
|
};
|
||
|
|
||
|
@Override
|
||
|
public int describeContents() {
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public void writeToParcel(Parcel out, int flags) {
|
||
|
out.writeInt(mWindowType);
|
||
|
out.writeTypedObject(mInsetsSize, flags);
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public String toString() {
|
||
|
StringBuilder sb = new StringBuilder(32);
|
||
|
sb.append("TypedInsetsSize: {");
|
||
|
sb.append("windowType=").append(ViewDebug.intToString(
|
||
|
WindowManager.LayoutParams.class, "type", mWindowType));
|
||
|
sb.append(", insetsSize=").append(mInsetsSize);
|
||
|
sb.append("}");
|
||
|
return sb.toString();
|
||
|
}
|
||
|
|
||
|
@Override
|
||
|
public int hashCode() {
|
||
|
return Objects.hash(mWindowType, mInsetsSize);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
|