• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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 
17 
18 package android.view;
19 
20 import static android.view.WindowInsets.Type.FIRST;
21 import static android.view.WindowInsets.Type.IME;
22 import static android.view.WindowInsets.Type.LAST;
23 import static android.view.WindowInsets.Type.MANDATORY_SYSTEM_GESTURES;
24 import static android.view.WindowInsets.Type.SIDE_BARS;
25 import static android.view.WindowInsets.Type.SIZE;
26 import static android.view.WindowInsets.Type.SYSTEM_GESTURES;
27 import static android.view.WindowInsets.Type.TAPPABLE_ELEMENT;
28 import static android.view.WindowInsets.Type.TOP_BAR;
29 import static android.view.WindowInsets.Type.all;
30 import static android.view.WindowInsets.Type.compatSystemInsets;
31 import static android.view.WindowInsets.Type.indexOf;
32 
33 import android.annotation.IntDef;
34 import android.annotation.IntRange;
35 import android.annotation.NonNull;
36 import android.annotation.Nullable;
37 import android.annotation.UnsupportedAppUsage;
38 import android.graphics.Insets;
39 import android.graphics.Rect;
40 import android.util.SparseArray;
41 import android.view.WindowInsets.Type.InsetType;
42 import android.view.inputmethod.EditorInfo;
43 import android.view.inputmethod.InputMethod;
44 
45 import com.android.internal.util.Preconditions;
46 
47 import java.lang.annotation.Retention;
48 import java.lang.annotation.RetentionPolicy;
49 import java.util.Arrays;
50 import java.util.Objects;
51 
52 /**
53  * Describes a set of insets for window content.
54  *
55  * <p>WindowInsets are immutable and may be expanded to include more inset types in the future.
56  * To adjust insets, use one of the supplied clone methods to obtain a new WindowInsets instance
57  * with the adjusted properties.</p>
58  *
59  * <p>Note: Before {@link android.os.Build.VERSION_CODES#P P}, WindowInsets instances were only
60  * immutable during a single layout pass (i.e. would return the same values between
61  * {@link View#onApplyWindowInsets} and {@link View#onLayout}, but could return other values
62  * otherwise). Starting with {@link android.os.Build.VERSION_CODES#P P}, WindowInsets are
63  * always immutable and implement equality.
64  *
65  * @see View.OnApplyWindowInsetsListener
66  * @see View#onApplyWindowInsets(WindowInsets)
67  */
68 public final class WindowInsets {
69 
70     private final Insets[] mTypeInsetsMap;
71     private final Insets[] mTypeMaxInsetsMap;
72     private final boolean[] mTypeVisibilityMap;
73 
74     @Nullable private Rect mTempRect;
75     private final boolean mIsRound;
76     @Nullable private final DisplayCutout mDisplayCutout;
77 
78     /**
79      * In multi-window we force show the navigation bar. Because we don't want that the surface size
80      * changes in this mode, we instead have a flag whether the navigation bar size should always
81      * be consumed, so the app is treated like there is no virtual navigation bar at all.
82      */
83     private final boolean mAlwaysConsumeSystemBars;
84 
85     private final boolean mSystemWindowInsetsConsumed;
86     private final boolean mStableInsetsConsumed;
87     private final boolean mDisplayCutoutConsumed;
88 
89     /**
90      * Since new insets may be added in the future that existing apps couldn't
91      * know about, this fully empty constant shouldn't be made available to apps
92      * since it would allow them to inadvertently consume unknown insets by returning it.
93      * @hide
94      */
95     @UnsupportedAppUsage
96     public static final WindowInsets CONSUMED;
97 
98     static {
99         CONSUMED = new WindowInsets((Rect) null, null, false, false, null);
100     }
101 
102     /**
103      * Construct a new WindowInsets from individual insets.
104      *
105      * A {@code null} inset indicates that the respective inset is consumed.
106      *
107      * @hide
108      * @deprecated Use {@link WindowInsets(SparseArray, SparseArray, boolean, boolean, DisplayCutout)}
109      */
WindowInsets(Rect systemWindowInsetsRect, Rect stableInsetsRect, boolean isRound, boolean alwaysConsumeSystemBars, DisplayCutout displayCutout)110     public WindowInsets(Rect systemWindowInsetsRect, Rect stableInsetsRect,
111             boolean isRound, boolean alwaysConsumeSystemBars, DisplayCutout displayCutout) {
112         this(createCompatTypeMap(systemWindowInsetsRect), createCompatTypeMap(stableInsetsRect),
113                 createCompatVisibilityMap(createCompatTypeMap(systemWindowInsetsRect)),
114                 isRound, alwaysConsumeSystemBars, displayCutout);
115     }
116 
117     /**
118      * Construct a new WindowInsets from individual insets.
119      *
120      * {@code typeInsetsMap} and {@code typeMaxInsetsMap} are a map of indexOf(type) -> insets that
121      * contain the information what kind of system bars causes how much insets. The insets in this
122      * map are non-additive; i.e. they have the same origin. In other words: If two system bars
123      * overlap on one side, the insets of the larger bar will also include the insets of the smaller
124      * bar.
125      *
126      * {@code null} type inset map indicates that the respective inset is fully consumed.
127      * @hide
128      */
WindowInsets(@ullable Insets[] typeInsetsMap, @Nullable Insets[] typeMaxInsetsMap, boolean[] typeVisibilityMap, boolean isRound, boolean alwaysConsumeSystemBars, DisplayCutout displayCutout)129     public WindowInsets(@Nullable Insets[] typeInsetsMap,
130             @Nullable Insets[] typeMaxInsetsMap,
131             boolean[] typeVisibilityMap,
132             boolean isRound,
133             boolean alwaysConsumeSystemBars, DisplayCutout displayCutout) {
134         mSystemWindowInsetsConsumed = typeInsetsMap == null;
135         mTypeInsetsMap = mSystemWindowInsetsConsumed
136                 ? new Insets[SIZE]
137                 : typeInsetsMap.clone();
138 
139         mStableInsetsConsumed = typeMaxInsetsMap == null;
140         mTypeMaxInsetsMap = mStableInsetsConsumed
141                 ? new Insets[SIZE]
142                 : typeMaxInsetsMap.clone();
143 
144         mTypeVisibilityMap = typeVisibilityMap;
145         mIsRound = isRound;
146         mAlwaysConsumeSystemBars = alwaysConsumeSystemBars;
147 
148         mDisplayCutoutConsumed = displayCutout == null;
149         mDisplayCutout = (mDisplayCutoutConsumed || displayCutout.isEmpty())
150                 ? null : displayCutout;
151     }
152 
153     /**
154      * Construct a new WindowInsets, copying all values from a source WindowInsets.
155      *
156      * @param src Source to copy insets from
157      */
WindowInsets(WindowInsets src)158     public WindowInsets(WindowInsets src) {
159         this(src.mSystemWindowInsetsConsumed ? null : src.mTypeInsetsMap,
160                 src.mStableInsetsConsumed ? null : src.mTypeMaxInsetsMap,
161                 src.mTypeVisibilityMap, src.mIsRound,
162                 src.mAlwaysConsumeSystemBars, displayCutoutCopyConstructorArgument(src));
163     }
164 
displayCutoutCopyConstructorArgument(WindowInsets w)165     private static DisplayCutout displayCutoutCopyConstructorArgument(WindowInsets w) {
166         if (w.mDisplayCutoutConsumed) {
167             return null;
168         } else if (w.mDisplayCutout == null) {
169             return DisplayCutout.NO_CUTOUT;
170         } else {
171             return w.mDisplayCutout;
172         }
173     }
174 
175     /**
176      * @return The insets that include system bars indicated by {@code typeMask}, taken from
177      *         {@code typeInsetMap}.
178      */
getInsets(Insets[] typeInsetsMap, @InsetType int typeMask)179     private static Insets getInsets(Insets[] typeInsetsMap, @InsetType int typeMask) {
180         Insets result = null;
181         for (int i = FIRST; i <= LAST; i = i << 1) {
182             if ((typeMask & i) == 0) {
183                 continue;
184             }
185             Insets insets = typeInsetsMap[indexOf(i)];
186             if (insets == null) {
187                 continue;
188             }
189             if (result == null) {
190                 result = insets;
191             } else {
192                 result = Insets.max(result, insets);
193             }
194         }
195         return result == null ? Insets.NONE : result;
196     }
197 
198     /**
199      * Sets all entries in {@code typeInsetsMap} that belong to {@code typeMask} to {@code insets},
200      */
setInsets(Insets[] typeInsetsMap, @InsetType int typeMask, Insets insets)201     private static void setInsets(Insets[] typeInsetsMap, @InsetType int typeMask, Insets insets) {
202         for (int i = FIRST; i <= LAST; i = i << 1) {
203             if ((typeMask & i) == 0) {
204                 continue;
205             }
206             typeInsetsMap[indexOf(i)] = insets;
207         }
208     }
209 
210     /** @hide */
211     @UnsupportedAppUsage
WindowInsets(Rect systemWindowInsets)212     public WindowInsets(Rect systemWindowInsets) {
213         this(createCompatTypeMap(systemWindowInsets), null, new boolean[SIZE], false, false, null);
214     }
215 
216     /**
217      * Creates a indexOf(type) -> inset map for which the {@code insets} is just mapped to
218      * {@link InsetType#topBar()} and {@link InsetType#sideBars()}, depending on the location of the
219      * inset.
220      */
createCompatTypeMap(@ullable Rect insets)221     private static Insets[] createCompatTypeMap(@Nullable Rect insets) {
222         if (insets == null) {
223             return null;
224         }
225         Insets[] typeInsetMap = new Insets[SIZE];
226         assignCompatInsets(typeInsetMap, insets);
227         return typeInsetMap;
228     }
229 
230     /**
231      * @hide
232      */
assignCompatInsets(Insets[] typeInsetMap, Rect insets)233     static void assignCompatInsets(Insets[] typeInsetMap, Rect insets) {
234         typeInsetMap[indexOf(TOP_BAR)] = Insets.of(0, insets.top, 0, 0);
235         typeInsetMap[indexOf(SIDE_BARS)] = Insets.of(insets.left, 0, insets.right, insets.bottom);
236     }
237 
createCompatVisibilityMap(@ullable Insets[] typeInsetMap)238     private static boolean[] createCompatVisibilityMap(@Nullable Insets[] typeInsetMap) {
239         boolean[] typeVisibilityMap = new boolean[SIZE];
240         if (typeInsetMap == null) {
241             return typeVisibilityMap;
242         }
243         for (int i = FIRST; i <= LAST; i = i << 1) {
244             int index = indexOf(i);
245             if (!Insets.NONE.equals(typeInsetMap[index])) {
246                 typeVisibilityMap[index] = true;
247             }
248         }
249         return typeVisibilityMap;
250     }
251 
252     /**
253      * Used to provide a safe copy of the system window insets to pass through
254      * to the existing fitSystemWindows method and other similar internals.
255      * @hide
256      *
257      * @deprecated use {@link #getSystemWindowInsets()} instead.
258      */
259     @Deprecated
260     @NonNull
getSystemWindowInsetsAsRect()261     public Rect getSystemWindowInsetsAsRect() {
262         if (mTempRect == null) {
263             mTempRect = new Rect();
264         }
265         Insets insets = getSystemWindowInsets();
266         mTempRect.set(insets.left, insets.top, insets.right, insets.bottom);
267         return mTempRect;
268     }
269 
270     /**
271      * Returns the system window insets in pixels.
272      *
273      * <p>The system window inset represents the area of a full-screen window that is
274      * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
275      * </p>
276      *
277      * @return The system window insets
278      */
279     @NonNull
getSystemWindowInsets()280     public Insets getSystemWindowInsets() {
281         return getInsets(mTypeInsetsMap, compatSystemInsets());
282     }
283 
284     /**
285      * Returns the insets of a specific set of windows causing insets, denoted by the
286      * {@code typeMask} bit mask of {@link InsetType}s.
287      *
288      * @param typeMask Bit mask of {@link InsetType}s to query the insets for.
289      * @return The insets.
290      *
291      * @hide pending unhide
292      */
getInsets(@nsetType int typeMask)293     public Insets getInsets(@InsetType int typeMask) {
294         return getInsets(mTypeInsetsMap, typeMask);
295     }
296 
297     /**
298      * Returns the maximum amount of insets a specific set of windows can cause, denoted by the
299      * {@code typeMask} bit mask of {@link InsetType}s.
300      *
301      * <p>The maximum insets represents the area of a a window that that <b>may</b> be partially
302      * or fully obscured by the system window identified by {@code type}. This value does not
303      * change based on the visibility state of those elements. for example, if the status bar is
304      * normally shown, but temporarily hidden, the maximum inset will still provide the inset
305      * associated with the status bar being shown.</p>
306      *
307      * @param typeMask Bit mask of {@link InsetType}s to query the insets for.
308      * @return The insets.
309      *
310      * @throws IllegalArgumentException If the caller tries to query {@link Type#ime()}. Maximum
311      *                                  insets are not available for this type as the height of the
312      *                                  IME is dynamic depending on the {@link EditorInfo} of the
313      *                                  currently focused view, as well as the UI state of the IME.
314      * @hide pending unhide
315      */
getMaxInsets(@nsetType int typeMask)316     public Insets getMaxInsets(@InsetType int typeMask) throws IllegalArgumentException {
317         if ((typeMask & IME) != 0) {
318             throw new IllegalArgumentException("Unable to query the maximum insets for IME");
319         }
320         return getInsets(mTypeMaxInsetsMap, typeMask);
321     }
322 
323     /**
324      * Returns whether a set of windows that may cause insets is currently visible on screen,
325      * regardless of whether it actually overlaps with this window.
326      *
327      * @param typeMask Bit mask of {@link InsetType}s to query visibility status.
328      * @return {@code true} if and only if all windows included in {@code typeMask} are currently
329      *         visible on screen.
330      * @hide pending unhide
331      */
isVisible(@nsetType int typeMask)332     public boolean isVisible(@InsetType int typeMask) {
333         for (int i = FIRST; i <= LAST; i = i << 1) {
334             if ((typeMask & i) == 0) {
335                 continue;
336             }
337             if (!mTypeVisibilityMap[indexOf(i)]) {
338                 return false;
339             }
340         }
341         return true;
342     }
343 
344     /**
345      * Returns the left system window inset in pixels.
346      *
347      * <p>The system window inset represents the area of a full-screen window that is
348      * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
349      * </p>
350      *
351      * @return The left system window inset
352      */
getSystemWindowInsetLeft()353     public int getSystemWindowInsetLeft() {
354         return getSystemWindowInsets().left;
355     }
356 
357     /**
358      * Returns the top system window inset in pixels.
359      *
360      * <p>The system window inset represents the area of a full-screen window that is
361      * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
362      * </p>
363      *
364      * @return The top system window inset
365      */
getSystemWindowInsetTop()366     public int getSystemWindowInsetTop() {
367         return getSystemWindowInsets().top;
368     }
369 
370     /**
371      * Returns the right system window inset in pixels.
372      *
373      * <p>The system window inset represents the area of a full-screen window that is
374      * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
375      * </p>
376      *
377      * @return The right system window inset
378      */
getSystemWindowInsetRight()379     public int getSystemWindowInsetRight() {
380         return getSystemWindowInsets().right;
381     }
382 
383     /**
384      * Returns the bottom system window inset in pixels.
385      *
386      * <p>The system window inset represents the area of a full-screen window that is
387      * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
388      * </p>
389      *
390      * @return The bottom system window inset
391      */
getSystemWindowInsetBottom()392     public int getSystemWindowInsetBottom() {
393         return getSystemWindowInsets().bottom;
394     }
395 
396     /**
397      * Returns true if this WindowInsets has nonzero system window insets.
398      *
399      * <p>The system window inset represents the area of a full-screen window that is
400      * partially or fully obscured by the status bar, navigation bar, IME or other system windows.
401      * </p>
402      *
403      * @return true if any of the system window inset values are nonzero
404      */
hasSystemWindowInsets()405     public boolean hasSystemWindowInsets() {
406         return !getSystemWindowInsets().equals(Insets.NONE);
407     }
408 
409     /**
410      * Returns true if this WindowInsets has any nonzero insets.
411      *
412      * @return true if any inset values are nonzero
413      */
hasInsets()414     public boolean hasInsets() {
415         return !getInsets(mTypeInsetsMap, all()).equals(Insets.NONE)
416                 || !getInsets(mTypeMaxInsetsMap, all()).equals(Insets.NONE)
417                 || mDisplayCutout != null;
418     }
419 
420     /**
421      * Returns the display cutout if there is one.
422      *
423      * @return the display cutout or null if there is none
424      * @see DisplayCutout
425      */
426     @Nullable
getDisplayCutout()427     public DisplayCutout getDisplayCutout() {
428         return mDisplayCutout;
429     }
430 
431     /**
432      * Returns a copy of this WindowInsets with the cutout fully consumed.
433      *
434      * @return A modified copy of this WindowInsets
435      */
436     @NonNull
consumeDisplayCutout()437     public WindowInsets consumeDisplayCutout() {
438         return new WindowInsets(mSystemWindowInsetsConsumed ? null : mTypeInsetsMap,
439                 mStableInsetsConsumed ? null : mTypeMaxInsetsMap,
440                 mTypeVisibilityMap,
441                 mIsRound, mAlwaysConsumeSystemBars,
442                 null /* displayCutout */);
443     }
444 
445 
446     /**
447      * Check if these insets have been fully consumed.
448      *
449      * <p>Insets are considered "consumed" if the applicable <code>consume*</code> methods
450      * have been called such that all insets have been set to zero. This affects propagation of
451      * insets through the view hierarchy; insets that have not been fully consumed will continue
452      * to propagate down to child views.</p>
453      *
454      * <p>The result of this method is equivalent to the return value of
455      * {@link View#fitSystemWindows(android.graphics.Rect)}.</p>
456      *
457      * @return true if the insets have been fully consumed.
458      */
isConsumed()459     public boolean isConsumed() {
460         return mSystemWindowInsetsConsumed && mStableInsetsConsumed
461                 && mDisplayCutoutConsumed;
462     }
463 
464     /**
465      * Returns true if the associated window has a round shape.
466      *
467      * <p>A round window's left, top, right and bottom edges reach all the way to the
468      * associated edges of the window but the corners may not be visible. Views responding
469      * to round insets should take care to not lay out critical elements within the corners
470      * where they may not be accessible.</p>
471      *
472      * @return True if the window is round
473      */
isRound()474     public boolean isRound() {
475         return mIsRound;
476     }
477 
478     /**
479      * Returns a copy of this WindowInsets with the system window insets fully consumed.
480      *
481      * @return A modified copy of this WindowInsets
482      */
483     @NonNull
consumeSystemWindowInsets()484     public WindowInsets consumeSystemWindowInsets() {
485         return new WindowInsets(null, mStableInsetsConsumed ? null : mTypeMaxInsetsMap,
486                 mTypeVisibilityMap,
487                 mIsRound, mAlwaysConsumeSystemBars,
488                 displayCutoutCopyConstructorArgument(this));
489     }
490 
491     // TODO(b/119190588): replace @code with @link below
492     /**
493      * Returns a copy of this WindowInsets with selected system window insets replaced
494      * with new values.
495      *
496      * <p>Note: If the system window insets are already consumed, this method will return them
497      * unchanged on {@link android.os.Build.VERSION_CODES#Q Q} and later. Prior to
498      * {@link android.os.Build.VERSION_CODES#Q Q}, the new values were applied regardless of
499      * whether they were consumed, and this method returns invalid non-zero consumed insets.
500      *
501      * @param left New left inset in pixels
502      * @param top New top inset in pixels
503      * @param right New right inset in pixels
504      * @param bottom New bottom inset in pixels
505      * @return A modified copy of this WindowInsets
506      * @deprecated use {@code Builder#Builder(WindowInsets)} with
507      *             {@link Builder#setSystemWindowInsets(Insets)} instead.
508      */
509     @Deprecated
510     @NonNull
replaceSystemWindowInsets(int left, int top, int right, int bottom)511     public WindowInsets replaceSystemWindowInsets(int left, int top, int right, int bottom) {
512         // Compat edge case: what should this do if the insets have already been consumed?
513         // On platforms prior to Q, the behavior was to override the insets with non-zero values,
514         // but leave them consumed, which is invalid (consumed insets must be zero).
515         // The behavior is now keeping them consumed and discarding the new insets.
516         if (mSystemWindowInsetsConsumed) {
517             return this;
518         }
519         return new Builder(this).setSystemWindowInsets(Insets.of(left, top, right, bottom)).build();
520     }
521 
522     // TODO(b/119190588): replace @code with @link below
523     /**
524      * Returns a copy of this WindowInsets with selected system window insets replaced
525      * with new values.
526      *
527      * <p>Note: If the system window insets are already consumed, this method will return them
528      * unchanged on {@link android.os.Build.VERSION_CODES#Q Q} and later. Prior to
529      * {@link android.os.Build.VERSION_CODES#Q Q}, the new values were applied regardless of
530      * whether they were consumed, and this method returns invalid non-zero consumed insets.
531      *
532      * @param systemWindowInsets New system window insets. Each field is the inset in pixels
533      *                           for that edge
534      * @return A modified copy of this WindowInsets
535      * @deprecated use {@code Builder#Builder(WindowInsets)} with
536      *             {@link Builder#setSystemWindowInsets(Insets)} instead.
537      */
538     @Deprecated
539     @NonNull
replaceSystemWindowInsets(Rect systemWindowInsets)540     public WindowInsets replaceSystemWindowInsets(Rect systemWindowInsets) {
541         return replaceSystemWindowInsets(systemWindowInsets.left, systemWindowInsets.top,
542                 systemWindowInsets.right, systemWindowInsets.bottom);
543     }
544 
545     /**
546      * Returns the stable insets in pixels.
547      *
548      * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
549      * partially or fully obscured by the system UI elements.  This value does not change
550      * based on the visibility state of those elements; for example, if the status bar is
551      * normally shown, but temporarily hidden, the stable inset will still provide the inset
552      * associated with the status bar being shown.</p>
553      *
554      * @return The stable insets
555      */
556     @NonNull
getStableInsets()557     public Insets getStableInsets() {
558         return getInsets(mTypeMaxInsetsMap, compatSystemInsets());
559     }
560 
561     /**
562      * Returns the top stable inset in pixels.
563      *
564      * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
565      * partially or fully obscured by the system UI elements.  This value does not change
566      * based on the visibility state of those elements; for example, if the status bar is
567      * normally shown, but temporarily hidden, the stable inset will still provide the inset
568      * associated with the status bar being shown.</p>
569      *
570      * @return The top stable inset
571      */
getStableInsetTop()572     public int getStableInsetTop() {
573         return getStableInsets().top;
574     }
575 
576     /**
577      * Returns the left stable inset in pixels.
578      *
579      * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
580      * partially or fully obscured by the system UI elements.  This value does not change
581      * based on the visibility state of those elements; for example, if the status bar is
582      * normally shown, but temporarily hidden, the stable inset will still provide the inset
583      * associated with the status bar being shown.</p>
584      *
585      * @return The left stable inset
586      */
getStableInsetLeft()587     public int getStableInsetLeft() {
588         return getStableInsets().left;
589     }
590 
591     /**
592      * Returns the right stable inset in pixels.
593      *
594      * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
595      * partially or fully obscured by the system UI elements.  This value does not change
596      * based on the visibility state of those elements; for example, if the status bar is
597      * normally shown, but temporarily hidden, the stable inset will still provide the inset
598      * associated with the status bar being shown.</p>
599      *
600      * @return The right stable inset
601      */
getStableInsetRight()602     public int getStableInsetRight() {
603         return getStableInsets().right;
604     }
605 
606     /**
607      * Returns the bottom stable inset in pixels.
608      *
609      * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
610      * partially or fully obscured by the system UI elements.  This value does not change
611      * based on the visibility state of those elements; for example, if the status bar is
612      * normally shown, but temporarily hidden, the stable inset will still provide the inset
613      * associated with the status bar being shown.</p>
614      *
615      * @return The bottom stable inset
616      */
getStableInsetBottom()617     public int getStableInsetBottom() {
618         return getStableInsets().bottom;
619     }
620 
621     /**
622      * Returns true if this WindowInsets has nonzero stable insets.
623      *
624      * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
625      * partially or fully obscured by the system UI elements.  This value does not change
626      * based on the visibility state of those elements; for example, if the status bar is
627      * normally shown, but temporarily hidden, the stable inset will still provide the inset
628      * associated with the status bar being shown.</p>
629      *
630      * @return true if any of the stable inset values are nonzero
631      */
hasStableInsets()632     public boolean hasStableInsets() {
633         return !getStableInsets().equals(Insets.NONE);
634     }
635 
636     /**
637      * Returns the system gesture insets.
638      *
639      * <p>The system gesture insets represent the area of a window where system gestures have
640      * priority and may consume some or all touch input, e.g. due to the a system bar
641      * occupying it, or it being reserved for touch-only gestures.
642      *
643      * <p>An app can declare priority over system gestures with
644      * {@link View#setSystemGestureExclusionRects} outside of the
645      * {@link #getMandatorySystemGestureInsets() mandatory system gesture insets}.
646      *
647      * <p>Simple taps are guaranteed to reach the window even within the system gesture insets,
648      * as long as they are outside the {@link #getTappableElementInsets() system window insets}.
649      *
650      * <p>When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned
651      * even when the system gestures are inactive due to
652      * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or
653      * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}.
654      *
655      * <p>This inset is consumed together with the {@link #getSystemWindowInsets()
656      * system window insets} by {@link #consumeSystemWindowInsets()}.
657      *
658      * @see #getMandatorySystemGestureInsets
659      */
660     @NonNull
getSystemGestureInsets()661     public Insets getSystemGestureInsets() {
662         return getInsets(mTypeInsetsMap, SYSTEM_GESTURES);
663     }
664 
665     /**
666      * Returns the mandatory system gesture insets.
667      *
668      * <p>The mandatory system gesture insets represent the area of a window where mandatory system
669      * gestures have priority and may consume some or all touch input, e.g. due to the a system bar
670      * occupying it, or it being reserved for touch-only gestures.
671      *
672      * <p>In contrast to {@link #getSystemGestureInsets regular system gestures}, <b>mandatory</b>
673      * system gestures cannot be overriden by {@link View#setSystemGestureExclusionRects}.
674      *
675      * <p>Simple taps are guaranteed to reach the window even within the system gesture insets,
676      * as long as they are outside the {@link #getTappableElementInsets() system window insets}.
677      *
678      * <p>When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned
679      * even when the system gestures are inactive due to
680      * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or
681      * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}.
682      *
683      * <p>This inset is consumed together with the {@link #getSystemWindowInsets()
684      * system window insets} by {@link #consumeSystemWindowInsets()}.
685      *
686      * @see #getSystemGestureInsets
687      */
688     @NonNull
getMandatorySystemGestureInsets()689     public Insets getMandatorySystemGestureInsets() {
690         return getInsets(mTypeInsetsMap, MANDATORY_SYSTEM_GESTURES);
691     }
692 
693     /**
694      * Returns the tappable element insets.
695      *
696      * <p>The tappable element insets represent how much tappable elements <b>must at least</b> be
697      * inset to remain both tappable and visually unobstructed by persistent system windows.
698      *
699      * <p>This may be smaller than {@link #getSystemWindowInsets()} if the system window is
700      * largely transparent and lets through simple taps (but not necessarily more complex gestures).
701      *
702      * <p>Note that generally, tappable elements <strong>should</strong> be aligned with the
703      * {@link #getSystemWindowInsets() system window insets} instead to avoid overlapping with the
704      * system bars.
705      *
706      * <p>When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned
707      * even when the area covered by the inset would be tappable due to
708      * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or
709      * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}.
710      *
711      * <p>This inset is consumed together with the {@link #getSystemWindowInsets()
712      * system window insets} by {@link #consumeSystemWindowInsets()}.
713      */
714     @NonNull
getTappableElementInsets()715     public Insets getTappableElementInsets() {
716         return getInsets(mTypeInsetsMap, TAPPABLE_ELEMENT);
717     }
718 
719     /**
720      * Returns a copy of this WindowInsets with the stable insets fully consumed.
721      *
722      * @return A modified copy of this WindowInsets
723      */
724     @NonNull
consumeStableInsets()725     public WindowInsets consumeStableInsets() {
726         return new WindowInsets(mSystemWindowInsetsConsumed ? null : mTypeInsetsMap, null,
727                 mTypeVisibilityMap, mIsRound, mAlwaysConsumeSystemBars,
728                 displayCutoutCopyConstructorArgument(this));
729     }
730 
731     /**
732      * @hide
733      */
shouldAlwaysConsumeSystemBars()734     public boolean shouldAlwaysConsumeSystemBars() {
735         return mAlwaysConsumeSystemBars;
736     }
737 
738     @Override
toString()739     public String toString() {
740         return "WindowInsets{systemWindowInsets=" + getSystemWindowInsets()
741                 + " stableInsets=" + getStableInsets()
742                 + " sysGestureInsets=" + getSystemGestureInsets()
743                 + (mDisplayCutout != null ? " cutout=" + mDisplayCutout : "")
744                 + (isRound() ? " round" : "")
745                 + "}";
746     }
747 
748     /**
749      * Returns a copy of this instance inset in the given directions.
750      *
751      * @see #inset(int, int, int, int)
752      * @deprecated use {@link #inset(Insets)}
753      * @hide
754      */
755     @Deprecated
756     @NonNull
inset(Rect r)757     public WindowInsets inset(Rect r) {
758         return inset(r.left, r.top, r.right, r.bottom);
759     }
760 
761     /**
762      * Returns a copy of this instance inset in the given directions.
763      *
764      * @see #inset(int, int, int, int)
765      * @hide
766      */
767     @NonNull
inset(Insets insets)768     public WindowInsets inset(Insets insets) {
769         return inset(insets.left, insets.top, insets.right, insets.bottom);
770     }
771 
772     /**
773      * Returns a copy of this instance inset in the given directions.
774      *
775      * This is intended for dispatching insets to areas of the window that are smaller than the
776      * current area.
777      *
778      * <p>Example:
779      * <pre>
780      * childView.dispatchApplyWindowInsets(insets.inset(
781      *         childMarginLeft, childMarginTop, childMarginBottom, childMarginRight));
782      * </pre>
783      *
784      * @param left the amount of insets to remove from the left. Must be non-negative.
785      * @param top the amount of insets to remove from the top. Must be non-negative.
786      * @param right the amount of insets to remove from the right. Must be non-negative.
787      * @param bottom the amount of insets to remove from the bottom. Must be non-negative.
788      *
789      * @return the inset insets
790      */
791     @NonNull
inset(@ntRangefrom = 0) int left, @IntRange(from = 0) int top, @IntRange(from = 0) int right, @IntRange(from = 0) int bottom)792     public WindowInsets inset(@IntRange(from = 0) int left, @IntRange(from = 0) int top,
793             @IntRange(from = 0) int right, @IntRange(from = 0) int bottom) {
794         Preconditions.checkArgumentNonnegative(left);
795         Preconditions.checkArgumentNonnegative(top);
796         Preconditions.checkArgumentNonnegative(right);
797         Preconditions.checkArgumentNonnegative(bottom);
798 
799         return new WindowInsets(
800                 mSystemWindowInsetsConsumed
801                         ? null
802                         : insetInsets(mTypeInsetsMap, left, top, right, bottom),
803                 mStableInsetsConsumed
804                         ? null
805                         : insetInsets(mTypeMaxInsetsMap, left, top, right, bottom),
806                 mTypeVisibilityMap,
807                 mIsRound, mAlwaysConsumeSystemBars,
808                 mDisplayCutoutConsumed
809                         ? null
810                         : mDisplayCutout == null
811                                 ? DisplayCutout.NO_CUTOUT
812                                 : mDisplayCutout.inset(left, top, right, bottom));
813     }
814 
815     @Override
equals(Object o)816     public boolean equals(Object o) {
817         if (this == o) return true;
818         if (o == null || !(o instanceof WindowInsets)) return false;
819         WindowInsets that = (WindowInsets) o;
820 
821         return mIsRound == that.mIsRound
822                 && mAlwaysConsumeSystemBars == that.mAlwaysConsumeSystemBars
823                 && mSystemWindowInsetsConsumed == that.mSystemWindowInsetsConsumed
824                 && mStableInsetsConsumed == that.mStableInsetsConsumed
825                 && mDisplayCutoutConsumed == that.mDisplayCutoutConsumed
826                 && Arrays.equals(mTypeInsetsMap, that.mTypeInsetsMap)
827                 && Arrays.equals(mTypeMaxInsetsMap, that.mTypeMaxInsetsMap)
828                 && Arrays.equals(mTypeVisibilityMap, that.mTypeVisibilityMap)
829                 && Objects.equals(mDisplayCutout, that.mDisplayCutout);
830     }
831 
832     @Override
hashCode()833     public int hashCode() {
834         return Objects.hash(Arrays.hashCode(mTypeInsetsMap), Arrays.hashCode(mTypeMaxInsetsMap),
835                 Arrays.hashCode(mTypeVisibilityMap), mIsRound, mDisplayCutout,
836                 mAlwaysConsumeSystemBars, mSystemWindowInsetsConsumed, mStableInsetsConsumed,
837                 mDisplayCutoutConsumed);
838     }
839 
840 
841     /**
842      * Insets every inset in {@code typeInsetsMap} by the specified left, top, right, bottom.
843      *
844      * @return {@code typeInsetsMap} if no inset was modified; a copy of the map with the modified
845      *          insets otherwise.
846      */
insetInsets( Insets[] typeInsetsMap, int left, int top, int right, int bottom)847     private static Insets[] insetInsets(
848             Insets[] typeInsetsMap, int left, int top, int right, int bottom) {
849         boolean cloned = false;
850         for (int i = 0; i < SIZE; i++) {
851             Insets insets = typeInsetsMap[i];
852             if (insets == null) {
853                 continue;
854             }
855             Insets insetInsets = insetInsets(insets, left, top, right, bottom);
856             if (insetInsets != insets) {
857                 if (!cloned) {
858                     typeInsetsMap = typeInsetsMap.clone();
859                     cloned = true;
860                 }
861                 typeInsetsMap[i] = insetInsets;
862             }
863         }
864         return typeInsetsMap;
865     }
866 
insetInsets(Insets insets, int left, int top, int right, int bottom)867     private static Insets insetInsets(Insets insets, int left, int top, int right, int bottom) {
868         int newLeft = Math.max(0, insets.left - left);
869         int newTop = Math.max(0, insets.top - top);
870         int newRight = Math.max(0, insets.right - right);
871         int newBottom = Math.max(0, insets.bottom - bottom);
872         if (newLeft == left && newTop == top && newRight == right && newBottom == bottom) {
873             return insets;
874         }
875         return Insets.of(newLeft, newTop, newRight, newBottom);
876     }
877 
878     /**
879      * @return whether system window insets have been consumed.
880      */
isSystemWindowInsetsConsumed()881     boolean isSystemWindowInsetsConsumed() {
882         return mSystemWindowInsetsConsumed;
883     }
884 
885     /**
886      * Builder for WindowInsets.
887      */
888     public static final class Builder {
889 
890         private final Insets[] mTypeInsetsMap;
891         private final Insets[] mTypeMaxInsetsMap;
892         private final boolean[] mTypeVisibilityMap;
893         private boolean mSystemInsetsConsumed = true;
894         private boolean mStableInsetsConsumed = true;
895 
896         private DisplayCutout mDisplayCutout;
897 
898         private boolean mIsRound;
899         private boolean mAlwaysConsumeSystemBars;
900 
901         /**
902          * Creates a builder where all insets are initially consumed.
903          */
Builder()904         public Builder() {
905             mTypeInsetsMap = new Insets[SIZE];
906             mTypeMaxInsetsMap = new Insets[SIZE];
907             mTypeVisibilityMap = new boolean[SIZE];
908         }
909 
910         /**
911          * Creates a builder where all insets are initialized from {@link WindowInsets}.
912          *
913          * @param insets the instance to initialize from.
914          */
Builder(@onNull WindowInsets insets)915         public Builder(@NonNull WindowInsets insets) {
916             mTypeInsetsMap = insets.mTypeInsetsMap.clone();
917             mTypeMaxInsetsMap = insets.mTypeMaxInsetsMap.clone();
918             mTypeVisibilityMap = insets.mTypeVisibilityMap.clone();
919             mSystemInsetsConsumed = insets.mSystemWindowInsetsConsumed;
920             mStableInsetsConsumed = insets.mStableInsetsConsumed;
921             mDisplayCutout = displayCutoutCopyConstructorArgument(insets);
922             mIsRound = insets.mIsRound;
923             mAlwaysConsumeSystemBars = insets.mAlwaysConsumeSystemBars;
924         }
925 
926         /**
927          * Sets system window insets in pixels.
928          *
929          * <p>The system window inset represents the area of a full-screen window that is
930          * partially or fully obscured by the status bar, navigation bar, IME or other system
931          * windows.</p>
932          *
933          * @see #getSystemWindowInsets()
934          * @return itself
935          */
936         @NonNull
setSystemWindowInsets(@onNull Insets systemWindowInsets)937         public Builder setSystemWindowInsets(@NonNull Insets systemWindowInsets) {
938             Preconditions.checkNotNull(systemWindowInsets);
939             assignCompatInsets(mTypeInsetsMap, systemWindowInsets.toRect());
940             mSystemInsetsConsumed = false;
941             return this;
942         }
943 
944         /**
945          * Sets system gesture insets in pixels.
946          *
947          * <p>The system gesture insets represent the area of a window where system gestures have
948          * priority and may consume some or all touch input, e.g. due to the a system bar
949          * occupying it, or it being reserved for touch-only gestures.
950          *
951          * @see #getSystemGestureInsets()
952          * @return itself
953          */
954         @NonNull
setSystemGestureInsets(@onNull Insets insets)955         public Builder setSystemGestureInsets(@NonNull Insets insets) {
956             WindowInsets.setInsets(mTypeInsetsMap, SYSTEM_GESTURES, insets);
957             return this;
958         }
959 
960         /**
961          * Sets mandatory system gesture insets in pixels.
962          *
963          * <p>The mandatory system gesture insets represent the area of a window where mandatory
964          * system gestures have priority and may consume some or all touch input, e.g. due to the a
965          * system bar occupying it, or it being reserved for touch-only gestures.
966          *
967          * <p>In contrast to {@link #setSystemGestureInsets regular system gestures},
968          * <b>mandatory</b> system gestures cannot be overriden by
969          * {@link View#setSystemGestureExclusionRects}.
970          *
971          * @see #getMandatorySystemGestureInsets()
972          * @return itself
973          */
974         @NonNull
setMandatorySystemGestureInsets(@onNull Insets insets)975         public Builder setMandatorySystemGestureInsets(@NonNull Insets insets) {
976             WindowInsets.setInsets(mTypeInsetsMap, MANDATORY_SYSTEM_GESTURES, insets);
977             return this;
978         }
979 
980         /**
981          * Sets tappable element insets in pixels.
982          *
983          * <p>The tappable element insets represent how much tappable elements <b>must at least</b>
984          * be inset to remain both tappable and visually unobstructed by persistent system windows.
985          *
986          * @see #getTappableElementInsets()
987          * @return itself
988          */
989         @NonNull
setTappableElementInsets(@onNull Insets insets)990         public Builder setTappableElementInsets(@NonNull Insets insets) {
991             WindowInsets.setInsets(mTypeInsetsMap, TAPPABLE_ELEMENT, insets);
992             return this;
993         }
994 
995         /**
996          * Sets the insets of a specific window type in pixels.
997          *
998          * <p>The insets represents the area of a a window that is partially or fully obscured by
999          * the system windows identified by {@code typeMask}.
1000          * </p>
1001          *
1002          * @see #getInsets(int)
1003          *
1004          * @param typeMask The bitmask of {@link InsetType} to set the insets for.
1005          * @param insets The insets to set.
1006          *
1007          * @return itself
1008          * @hide pending unhide
1009          */
1010         @NonNull
setInsets(@nsetType int typeMask, @NonNull Insets insets)1011         public Builder setInsets(@InsetType int typeMask, @NonNull Insets insets) {
1012             Preconditions.checkNotNull(insets);
1013             WindowInsets.setInsets(mTypeInsetsMap, typeMask, insets);
1014             mSystemInsetsConsumed = false;
1015             return this;
1016         }
1017 
1018         /**
1019          * Sets the maximum amount of insets a specific window type in pixels.
1020          *
1021          * <p>The maximum insets represents the area of a a window that that <b>may</b> be partially
1022          * or fully obscured by the system windows identified by {@code typeMask}. This value does
1023          * not change based on the visibility state of those elements. for example, if the status
1024          * bar is normally shown, but temporarily hidden, the maximum inset will still provide the
1025          * inset associated with the status bar being shown.</p>
1026          *
1027          * @see #getMaxInsets(int)
1028          *
1029          * @param typeMask The bitmask of {@link InsetType} to set the insets for.
1030          * @param insets The insets to set.
1031          *
1032          * @return itself
1033          *
1034          * @throws IllegalArgumentException If {@code typeMask} contains {@link Type#ime()}. Maximum
1035          *                                  insets are not available for this type as the height of
1036          *                                  the IME is dynamic depending on the {@link EditorInfo}
1037          *                                  of the currently focused view, as well as the UI
1038          *                                  state of the IME.
1039          * @hide pending unhide
1040          */
1041         @NonNull
setMaxInsets(@nsetType int typeMask, @NonNull Insets insets)1042         public Builder setMaxInsets(@InsetType int typeMask, @NonNull Insets insets)
1043                 throws IllegalArgumentException{
1044             if (typeMask == IME) {
1045                 throw new IllegalArgumentException("Maximum inset not available for IME");
1046             }
1047             Preconditions.checkNotNull(insets);
1048             WindowInsets.setInsets(mTypeMaxInsetsMap, typeMask, insets);
1049             mStableInsetsConsumed = false;
1050             return this;
1051         }
1052 
1053         /**
1054          * Sets whether windows that can cause insets are currently visible on screen.
1055          *
1056          *
1057          * @see #isVisible(int)
1058          *
1059          * @param typeMask The bitmask of {@link InsetType} to set the visibility for.
1060          * @param visible Whether to mark the windows as visible or not.
1061          *
1062          * @return itself
1063          * @hide pending unhide
1064          */
1065         @NonNull
setVisible(@nsetType int typeMask, boolean visible)1066         public Builder setVisible(@InsetType int typeMask, boolean visible) {
1067             for (int i = FIRST; i <= LAST; i = i << 1) {
1068                 if ((typeMask & i) == 0) {
1069                     continue;
1070                 }
1071                 mTypeVisibilityMap[indexOf(i)] = visible;
1072             }
1073             return this;
1074         }
1075 
1076         /**
1077          * Sets the stable insets in pixels.
1078          *
1079          * <p>The stable inset represents the area of a full-screen window that <b>may</b> be
1080          * partially or fully obscured by the system UI elements.  This value does not change
1081          * based on the visibility state of those elements; for example, if the status bar is
1082          * normally shown, but temporarily hidden, the stable inset will still provide the inset
1083          * associated with the status bar being shown.</p>
1084          *
1085          * @see #getStableInsets()
1086          * @return itself
1087          */
1088         @NonNull
setStableInsets(@onNull Insets stableInsets)1089         public Builder setStableInsets(@NonNull Insets stableInsets) {
1090             Preconditions.checkNotNull(stableInsets);
1091             assignCompatInsets(mTypeMaxInsetsMap, stableInsets.toRect());
1092             mStableInsetsConsumed = false;
1093             return this;
1094         }
1095 
1096         /**
1097          * Sets the display cutout.
1098          *
1099          * @see #getDisplayCutout()
1100          * @param displayCutout the display cutout or null if there is none
1101          * @return itself
1102          */
1103         @NonNull
setDisplayCutout(@ullable DisplayCutout displayCutout)1104         public Builder setDisplayCutout(@Nullable DisplayCutout displayCutout) {
1105             mDisplayCutout = displayCutout != null ? displayCutout : DisplayCutout.NO_CUTOUT;
1106             return this;
1107         }
1108 
1109         /** @hide */
1110         @NonNull
setRound(boolean round)1111         public Builder setRound(boolean round) {
1112             mIsRound = round;
1113             return this;
1114         }
1115 
1116         /** @hide */
1117         @NonNull
setAlwaysConsumeSystemBars(boolean alwaysConsumeSystemBars)1118         public Builder setAlwaysConsumeSystemBars(boolean alwaysConsumeSystemBars) {
1119             mAlwaysConsumeSystemBars = alwaysConsumeSystemBars;
1120             return this;
1121         }
1122 
1123         /**
1124          * Builds a {@link WindowInsets} instance.
1125          *
1126          * @return the {@link WindowInsets} instance.
1127          */
1128         @NonNull
build()1129         public WindowInsets build() {
1130             return new WindowInsets(mSystemInsetsConsumed ? null : mTypeInsetsMap,
1131                     mStableInsetsConsumed ? null : mTypeMaxInsetsMap, mTypeVisibilityMap,
1132                     mIsRound, mAlwaysConsumeSystemBars, mDisplayCutout);
1133         }
1134     }
1135 
1136     /**
1137      * Class that defines different types of sources causing window insets.
1138      * @hide pending unhide
1139      */
1140     public static final class Type {
1141 
1142         static final int FIRST = 1 << 0;
1143         static final int TOP_BAR = FIRST;
1144 
1145         static final int IME = 1 << 1;
1146         static final int SIDE_BARS = 1 << 2;
1147 
1148         static final int SYSTEM_GESTURES = 1 << 3;
1149         static final int MANDATORY_SYSTEM_GESTURES = 1 << 4;
1150         static final int TAPPABLE_ELEMENT = 1 << 5;
1151 
1152         static final int LAST = 1 << 6;
1153         static final int SIZE = 7;
1154         static final int WINDOW_DECOR = LAST;
1155 
indexOf(@nsetType int type)1156         static int indexOf(@InsetType int type) {
1157             switch (type) {
1158                 case TOP_BAR:
1159                     return 0;
1160                 case IME:
1161                     return 1;
1162                 case SIDE_BARS:
1163                     return 2;
1164                 case SYSTEM_GESTURES:
1165                     return 3;
1166                 case MANDATORY_SYSTEM_GESTURES:
1167                     return 4;
1168                 case TAPPABLE_ELEMENT:
1169                     return 5;
1170                 case WINDOW_DECOR:
1171                     return 6;
1172                 default:
1173                     throw new IllegalArgumentException("type needs to be >= FIRST and <= LAST,"
1174                             + " type=" + type);
1175             }
1176         }
1177 
Type()1178         private Type() {
1179         }
1180 
1181         /** @hide */
1182         @Retention(RetentionPolicy.SOURCE)
1183         @IntDef(flag = true, value = { TOP_BAR, IME, SIDE_BARS, WINDOW_DECOR, SYSTEM_GESTURES,
1184                 MANDATORY_SYSTEM_GESTURES, TAPPABLE_ELEMENT})
1185         public @interface InsetType {
1186         }
1187 
1188         /**
1189          * @return An inset type representing the top bar of a window, which can be the status
1190          *         bar on handheld-like devices as well as a caption bar.
1191          */
topBar()1192         public static @InsetType int topBar() {
1193             return TOP_BAR;
1194         }
1195 
1196         /**
1197          * @return An inset type representing the window of an {@link InputMethod}.
1198          */
ime()1199         public static @InsetType int ime() {
1200             return IME;
1201         }
1202 
1203         /**
1204          * @return An inset type representing any system bars that are not {@link #topBar()}.
1205          */
sideBars()1206         public static @InsetType int sideBars() {
1207             return SIDE_BARS;
1208         }
1209 
1210         /**
1211          * @return An inset type representing decor that is being app-controlled.
1212          */
windowDecor()1213         public static @InsetType int windowDecor() {
1214             return WINDOW_DECOR;
1215         }
1216 
1217         /**
1218          * Returns an inset type representing the system gesture insets.
1219          *
1220          * <p>The system gesture insets represent the area of a window where system gestures have
1221          * priority and may consume some or all touch input, e.g. due to the a system bar
1222          * occupying it, or it being reserved for touch-only gestures.
1223          *
1224          * <p>Simple taps are guaranteed to reach the window even within the system gesture insets,
1225          * as long as they are outside the {@link #getSystemWindowInsets() system window insets}.
1226          *
1227          * <p>When {@link View#SYSTEM_UI_FLAG_LAYOUT_STABLE} is requested, an inset will be returned
1228          * even when the system gestures are inactive due to
1229          * {@link View#SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN} or
1230          * {@link View#SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION}.
1231          *
1232          * @see #getSystemGestureInsets()
1233          */
systemGestures()1234         public static @InsetType int systemGestures() {
1235             return SYSTEM_GESTURES;
1236         }
1237 
1238         /**
1239          * @see #getMandatorySystemGestureInsets
1240          */
mandatorySystemGestures()1241         public static @InsetType int mandatorySystemGestures() {
1242             return MANDATORY_SYSTEM_GESTURES;
1243         }
1244 
1245         /**
1246          * @see #getTappableElementInsets
1247          */
tappableElement()1248         public static @InsetType int tappableElement() {
1249             return TAPPABLE_ELEMENT;
1250         }
1251 
1252         /**
1253          * @return All system bars. Includes {@link #topBar()} as well as {@link #sideBars()}, but
1254          *         not {@link #ime()}.
1255          */
systemBars()1256         public static @InsetType int systemBars() {
1257             return TOP_BAR | SIDE_BARS;
1258         }
1259 
1260         /**
1261          * @return Inset types representing the list of bars that traditionally were denoted as
1262          *         system insets.
1263          * @hide
1264          */
compatSystemInsets()1265         static @InsetType int compatSystemInsets() {
1266             return TOP_BAR | SIDE_BARS | IME;
1267         }
1268 
1269         /**
1270          * @return All inset types combined.
1271          *
1272          * TODO: Figure out if this makes sense at all, mixing e.g {@link #systemGestures()} and
1273          *       {@link #ime()} does not seem very useful.
1274          */
all()1275         public static @InsetType int all() {
1276             return 0xFFFFFFFF;
1277         }
1278     }
1279 }
1280