blob: 37034ee065ee72eb4ab008c7f6b3d7fc993cbebc [file] [log] [blame]
Jorim Jaggif96c90a2018-09-26 16:55:15 +02001/*
2 * Copyright (C) 2018 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.view;
18
Jorim Jaggi23a02a92020-01-29 15:30:36 +010019import static android.view.InsetsState.ITYPE_IME;
20
Jorim Jaggi4e04eb22020-01-09 16:42:14 +010021import android.annotation.Nullable;
Jorim Jaggif96c90a2018-09-26 16:55:15 +020022import android.graphics.Insets;
23import android.graphics.Rect;
24import android.os.Parcel;
25import android.os.Parcelable;
Tiger Huang332793b2019-10-29 23:21:27 +080026import android.view.InsetsState.InternalInsetsType;
Jorim Jaggif96c90a2018-09-26 16:55:15 +020027
28import java.io.PrintWriter;
Jorim Jaggi4e04eb22020-01-09 16:42:14 +010029import java.util.Objects;
Jorim Jaggif96c90a2018-09-26 16:55:15 +020030
31/**
32 * Represents the state of a single window generating insets for clients.
33 * @hide
34 */
35public class InsetsSource implements Parcelable {
36
Tiger Huang332793b2019-10-29 23:21:27 +080037 private final @InternalInsetsType int mType;
Jorim Jaggif96c90a2018-09-26 16:55:15 +020038
39 /** Frame of the source in screen coordinate space */
40 private final Rect mFrame;
Jorim Jaggi4e04eb22020-01-09 16:42:14 +010041 private @Nullable Rect mVisibleFrame;
Jorim Jaggif96c90a2018-09-26 16:55:15 +020042 private boolean mVisible;
43
44 private final Rect mTmpFrame = new Rect();
45
Tiger Huang332793b2019-10-29 23:21:27 +080046 public InsetsSource(@InternalInsetsType int type) {
Jorim Jaggif96c90a2018-09-26 16:55:15 +020047 mType = type;
48 mFrame = new Rect();
Jorim Jaggi0dd0cf92019-12-27 15:17:44 +010049 mVisible = InsetsState.getDefaultVisibility(type);
Jorim Jaggif96c90a2018-09-26 16:55:15 +020050 }
51
52 public InsetsSource(InsetsSource other) {
53 mType = other.mType;
54 mFrame = new Rect(other.mFrame);
55 mVisible = other.mVisible;
56 }
57
58 public void setFrame(Rect frame) {
59 mFrame.set(frame);
60 }
61
Jorim Jaggi4e04eb22020-01-09 16:42:14 +010062 public void setVisibleFrame(@Nullable Rect visibleFrame) {
63 mVisibleFrame = visibleFrame != null ? new Rect(visibleFrame) : visibleFrame;
64 }
65
Jorim Jaggif96c90a2018-09-26 16:55:15 +020066 public void setVisible(boolean visible) {
67 mVisible = visible;
68 }
69
Tiger Huang332793b2019-10-29 23:21:27 +080070 public @InternalInsetsType int getType() {
Jorim Jaggif96c90a2018-09-26 16:55:15 +020071 return mType;
72 }
73
74 public Rect getFrame() {
75 return mFrame;
76 }
77
Jorim Jaggi4e04eb22020-01-09 16:42:14 +010078 public @Nullable Rect getVisibleFrame() {
79 return mVisibleFrame;
80 }
81
Jorim Jaggie35c0592018-11-06 16:21:08 +010082 public boolean isVisible() {
83 return mVisible;
84 }
85
Jorim Jaggif96c90a2018-09-26 16:55:15 +020086 /**
87 * Calculates the insets this source will cause to a client window.
88 *
89 * @param relativeFrame The frame to calculate the insets relative to.
90 * @param ignoreVisibility If true, always reports back insets even if source isn't visible.
Jorim Jaggi5bb571d2018-11-06 14:42:04 +010091 * @return The resulting insets. The contract is that only one side will be occupied by a
92 * source.
Jorim Jaggif96c90a2018-09-26 16:55:15 +020093 */
94 public Insets calculateInsets(Rect relativeFrame, boolean ignoreVisibility) {
Jorim Jaggi4e04eb22020-01-09 16:42:14 +010095 return calculateInsets(relativeFrame, mFrame, ignoreVisibility);
96 }
97
98 /**
99 * Like {@link #calculateInsets(Rect, boolean)}, but will return visible insets.
100 */
101 public Insets calculateVisibleInsets(Rect relativeFrame) {
102 return calculateInsets(relativeFrame, mVisibleFrame != null ? mVisibleFrame : mFrame,
103 false /* ignoreVisibility */);
104 }
105
106 private Insets calculateInsets(Rect relativeFrame, Rect frame, boolean ignoreVisibility) {
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200107 if (!ignoreVisibility && !mVisible) {
108 return Insets.NONE;
109 }
Jorim Jaggi4e04eb22020-01-09 16:42:14 +0100110 if (!mTmpFrame.setIntersect(frame, relativeFrame)) {
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200111 return Insets.NONE;
112 }
113
Jorim Jaggi23a02a92020-01-29 15:30:36 +0100114 // TODO: Currently, non-floating IME always intersects at bottom due to issues with cutout.
115 // However, we should let the policy decide from the server.
116 if (getType() == ITYPE_IME) {
117 return Insets.of(0, 0, 0, mTmpFrame.height());
118 }
119
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200120 // Intersecting at top/bottom
121 if (mTmpFrame.width() == relativeFrame.width()) {
122 if (mTmpFrame.top == relativeFrame.top) {
123 return Insets.of(0, mTmpFrame.height(), 0, 0);
124 } else {
125 return Insets.of(0, 0, 0, mTmpFrame.height());
126 }
127 }
128 // Intersecting at left/right
129 else if (mTmpFrame.height() == relativeFrame.height()) {
130 if (mTmpFrame.left == relativeFrame.left) {
131 return Insets.of(mTmpFrame.width(), 0, 0, 0);
132 } else {
133 return Insets.of(0, 0, mTmpFrame.width(), 0);
134 }
135 } else {
136 return Insets.NONE;
137 }
138 }
139
140 public void dump(String prefix, PrintWriter pw) {
141 pw.print(prefix);
142 pw.print("InsetsSource type="); pw.print(InsetsState.typeToString(mType));
143 pw.print(" frame="); pw.print(mFrame.toShortString());
Jorim Jaggi4e04eb22020-01-09 16:42:14 +0100144 if (mVisibleFrame != null) {
145 pw.print(" visibleFrmae="); pw.print(mVisibleFrame.toShortString());
146 }
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200147 pw.print(" visible="); pw.print(mVisible);
148 pw.println();
149 }
150
151 @Override
152 public boolean equals(Object o) {
153 if (this == o) return true;
154 if (o == null || getClass() != o.getClass()) return false;
155
156 InsetsSource that = (InsetsSource) o;
157
158 if (mType != that.mType) return false;
159 if (mVisible != that.mVisible) return false;
Jorim Jaggi4e04eb22020-01-09 16:42:14 +0100160 if (!Objects.equals(mVisibleFrame, that.mVisibleFrame)) return false;
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200161 return mFrame.equals(that.mFrame);
162 }
163
164 @Override
165 public int hashCode() {
166 int result = mType;
167 result = 31 * result + mFrame.hashCode();
168 result = 31 * result + (mVisible ? 1 : 0);
169 return result;
170 }
171
172 public InsetsSource(Parcel in) {
173 mType = in.readInt();
174 mFrame = in.readParcelable(null /* loader */);
Jorim Jaggi4e04eb22020-01-09 16:42:14 +0100175 mVisibleFrame = in.readParcelable(null /* loader */);
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200176 mVisible = in.readBoolean();
177 }
178
179 @Override
180 public int describeContents() {
181 return 0;
182 }
183
184 @Override
185 public void writeToParcel(Parcel dest, int flags) {
186 dest.writeInt(mType);
187 dest.writeParcelable(mFrame, 0 /* flags*/);
Jorim Jaggi4e04eb22020-01-09 16:42:14 +0100188 dest.writeParcelable(mVisibleFrame, 0 /* flags */);
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200189 dest.writeBoolean(mVisible);
190 }
191
Jeff Sharkey9e8f83d2019-02-28 12:06:45 -0700192 public static final @android.annotation.NonNull Creator<InsetsSource> CREATOR = new Creator<InsetsSource>() {
Jorim Jaggif96c90a2018-09-26 16:55:15 +0200193
194 public InsetsSource createFromParcel(Parcel in) {
195 return new InsetsSource(in);
196 }
197
198 public InsetsSource[] newArray(int size) {
199 return new InsetsSource[size];
200 }
201 };
202}