1 /*
2  * Copyright (C) 2020 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 package android.view;
18 
19 import android.annotation.NonNull;
20 import android.annotation.Nullable;
21 import android.annotation.UiThread;
22 import android.graphics.Matrix;
23 import android.graphics.Point;
24 import android.graphics.Rect;
25 
26 import com.android.internal.util.FastMath;
27 
28 /**
29  * A target collects the set of contextual information for a ScrollCaptureHandler discovered during
30  * a {@link View#dispatchScrollCaptureSearch scroll capture search}.
31  *
32  * @hide
33  */
34 public final class ScrollCaptureTarget {
35     private final View mContainingView;
36     private final ScrollCaptureCallback mCallback;
37     private final Rect mLocalVisibleRect;
38     private final Point mPositionInWindow;
39     private final int mHint;
40     private Rect mScrollBounds;
41 
42     private final float[] mTmpFloatArr = new float[2];
43     private final Matrix mMatrixViewLocalToWindow = new Matrix();
44     private final Rect mTmpRect = new Rect();
45 
ScrollCaptureTarget(@onNull View scrollTarget, @NonNull Rect localVisibleRect, @NonNull Point positionInWindow, @NonNull ScrollCaptureCallback callback)46     public ScrollCaptureTarget(@NonNull View scrollTarget, @NonNull Rect localVisibleRect,
47             @NonNull Point positionInWindow, @NonNull ScrollCaptureCallback callback) {
48         mContainingView = scrollTarget;
49         mHint = mContainingView.getScrollCaptureHint();
50         mCallback = callback;
51         mLocalVisibleRect = localVisibleRect;
52         mPositionInWindow = positionInWindow;
53     }
54 
55     /** @return the hint that the {@code containing view} had during the scroll capture search */
56     @View.ScrollCaptureHint
getHint()57     public int getHint() {
58         return mHint;
59     }
60 
61     /** @return the {@link ScrollCaptureCallback} for this target */
62     @NonNull
getCallback()63     public ScrollCaptureCallback getCallback() {
64         return mCallback;
65     }
66 
67     /** @return the {@code containing view} for this {@link ScrollCaptureCallback callback} */
68     @NonNull
getContainingView()69     public View getContainingView() {
70         return mContainingView;
71     }
72 
73     /**
74      * Returns the un-clipped, visible bounds of the containing view during the scroll capture
75      * search. This is used to determine on-screen area to assist in selecting the primary target.
76      *
77      * @return the visible bounds of the {@code containing view} in view-local coordinates
78      */
79     @NonNull
getLocalVisibleRect()80     public Rect getLocalVisibleRect() {
81         return mLocalVisibleRect;
82     }
83 
84     /** @return the position of the {@code containing view} within the window */
85     @NonNull
getPositionInWindow()86     public Point getPositionInWindow() {
87         return mPositionInWindow;
88     }
89 
90     /** @return the {@code scroll bounds} for this {@link ScrollCaptureCallback callback} */
91     @Nullable
getScrollBounds()92     public Rect getScrollBounds() {
93         return mScrollBounds;
94     }
95 
96     /**
97      * Sets the scroll bounds rect to the intersection of provided rect and the current bounds of
98      * the {@code containing view}.
99      */
setScrollBounds(@ullable Rect scrollBounds)100     public void setScrollBounds(@Nullable Rect scrollBounds) {
101         mScrollBounds = Rect.copyOrNull(scrollBounds);
102         if (mScrollBounds == null) {
103             return;
104         }
105         if (!mScrollBounds.intersect(0, 0,
106                 mContainingView.getWidth(), mContainingView.getHeight())) {
107             mScrollBounds.setEmpty();
108         }
109     }
110 
zero(float[] pointArray)111     private static void zero(float[] pointArray) {
112         pointArray[0] = 0;
113         pointArray[1] = 0;
114     }
115 
roundIntoPoint(Point pointObj, float[] pointArray)116     private static void roundIntoPoint(Point pointObj, float[] pointArray) {
117         pointObj.x = FastMath.round(pointArray[0]);
118         pointObj.y = FastMath.round(pointArray[1]);
119     }
120 
121     /**
122      * Refresh the value of {@link #mLocalVisibleRect} and {@link #mPositionInWindow} based on the
123      * current state of the {@code containing view}.
124      */
125     @UiThread
updatePositionInWindow()126     public void updatePositionInWindow() {
127         mMatrixViewLocalToWindow.reset();
128         mContainingView.transformMatrixToGlobal(mMatrixViewLocalToWindow);
129 
130         zero(mTmpFloatArr);
131         mMatrixViewLocalToWindow.mapPoints(mTmpFloatArr);
132         roundIntoPoint(mPositionInWindow, mTmpFloatArr);
133     }
134 
135 }
136