blob: fffb323e6d500b24bc8de43efee65f2c2907018b [file] [log] [blame]
Adam Powell769b8632019-02-04 11:28:22 -08001/*
2 * Copyright (C) 2019 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
19import android.annotation.NonNull;
20import android.annotation.Nullable;
21import android.graphics.Rect;
22
Adam Powell5a40b712019-04-15 15:54:02 -070023import com.android.internal.util.Preconditions;
24
Adam Powell769b8632019-02-04 11:28:22 -080025import java.lang.ref.WeakReference;
26import java.util.ArrayList;
27import java.util.Collections;
28import java.util.Iterator;
29import java.util.List;
30
31/**
32 * Used by {@link ViewRootImpl} to track system gesture exclusion rects reported by views.
33 */
34class GestureExclusionTracker {
35 private boolean mGestureExclusionViewsChanged = false;
Adam Powell5a40b712019-04-15 15:54:02 -070036 private boolean mRootGestureExclusionRectsChanged = false;
37 private List<Rect> mRootGestureExclusionRects = Collections.emptyList();
Adam Powell769b8632019-02-04 11:28:22 -080038 private List<GestureExclusionViewInfo> mGestureExclusionViewInfos = new ArrayList<>();
39 private List<Rect> mGestureExclusionRects = Collections.emptyList();
40
41 public void updateRectsForView(@NonNull View view) {
42 boolean found = false;
43 final Iterator<GestureExclusionViewInfo> i = mGestureExclusionViewInfos.iterator();
44 while (i.hasNext()) {
45 final GestureExclusionViewInfo info = i.next();
46 final View v = info.getView();
Winson Chung05a36462019-08-29 15:16:27 -070047 if (v == null || !v.isAttachedToWindow() || !v.isAggregatedVisible()) {
Adam Powell769b8632019-02-04 11:28:22 -080048 mGestureExclusionViewsChanged = true;
49 i.remove();
50 continue;
51 }
52 if (v == view) {
53 found = true;
54 info.mDirty = true;
55 break;
56 }
57 }
58 if (!found && view.isAttachedToWindow()) {
59 mGestureExclusionViewInfos.add(new GestureExclusionViewInfo(view));
60 mGestureExclusionViewsChanged = true;
61 }
62 }
63
64 @Nullable
65 public List<Rect> computeChangedRects() {
Adam Powell5a40b712019-04-15 15:54:02 -070066 boolean changed = mRootGestureExclusionRectsChanged;
Adam Powell769b8632019-02-04 11:28:22 -080067 final Iterator<GestureExclusionViewInfo> i = mGestureExclusionViewInfos.iterator();
Adam Powell5a40b712019-04-15 15:54:02 -070068 final List<Rect> rects = new ArrayList<>(mRootGestureExclusionRects);
Adam Powell769b8632019-02-04 11:28:22 -080069 while (i.hasNext()) {
70 final GestureExclusionViewInfo info = i.next();
71 switch (info.update()) {
72 case GestureExclusionViewInfo.CHANGED:
73 changed = true;
74 // Deliberate fall-through
75 case GestureExclusionViewInfo.UNCHANGED:
76 rects.addAll(info.mExclusionRects);
77 break;
78 case GestureExclusionViewInfo.GONE:
79 mGestureExclusionViewsChanged = true;
80 i.remove();
81 break;
82 }
83 }
84 if (changed || mGestureExclusionViewsChanged) {
85 mGestureExclusionViewsChanged = false;
Adam Powell5a40b712019-04-15 15:54:02 -070086 mRootGestureExclusionRectsChanged = false;
Adam Powell769b8632019-02-04 11:28:22 -080087 if (!mGestureExclusionRects.equals(rects)) {
88 mGestureExclusionRects = rects;
89 return rects;
90 }
91 }
92 return null;
93 }
94
Adam Powell5a40b712019-04-15 15:54:02 -070095 public void setRootSystemGestureExclusionRects(@NonNull List<Rect> rects) {
96 Preconditions.checkNotNull(rects, "rects must not be null");
97 mRootGestureExclusionRects = rects;
98 mRootGestureExclusionRectsChanged = true;
99 }
100
101 @NonNull
102 public List<Rect> getRootSystemGestureExclusionRects() {
103 return mRootGestureExclusionRects;
104 }
105
Adam Powell769b8632019-02-04 11:28:22 -0800106 private static class GestureExclusionViewInfo {
107 public static final int CHANGED = 0;
108 public static final int UNCHANGED = 1;
109 public static final int GONE = 2;
110
111 private final WeakReference<View> mView;
112 boolean mDirty = true;
113 List<Rect> mExclusionRects = Collections.emptyList();
114
115 GestureExclusionViewInfo(View view) {
116 mView = new WeakReference<>(view);
117 }
118
119 public View getView() {
120 return mView.get();
121 }
122
123 public int update() {
124 final View excludedView = getView();
Winson Chung61cfd712019-08-22 16:36:18 -0700125 if (excludedView == null || !excludedView.isAttachedToWindow()
Winson Chung05a36462019-08-29 15:16:27 -0700126 || !excludedView.isAggregatedVisible()) return GONE;
Adam Powell769b8632019-02-04 11:28:22 -0800127 final List<Rect> localRects = excludedView.getSystemGestureExclusionRects();
128 final List<Rect> newRects = new ArrayList<>(localRects.size());
129 for (Rect src : localRects) {
130 Rect mappedRect = new Rect(src);
131 ViewParent p = excludedView.getParent();
132 if (p != null && p.getChildVisibleRect(excludedView, mappedRect, null)) {
133 newRects.add(mappedRect);
134 }
135 }
136
137 if (mExclusionRects.equals(localRects)) return UNCHANGED;
138 mExclusionRects = newRects;
139 return CHANGED;
140 }
141 }
142}