blob: 17d9864e4d25c3a1f0bc3a687b8dcfb729d45bd2 [file] [log] [blame]
Winson Chungfa7053782016-11-08 15:45:10 -08001/*
2 * Copyright (C) 2016 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 com.android.systemui.pip.phone;
18
19import android.app.IActivityManager;
20import android.graphics.PointF;
21import android.view.IPinnedStackController;
22import android.view.IPinnedStackListener;
23import android.view.IWindowManager;
24import android.view.MotionEvent;
25import android.view.VelocityTracker;
26import android.view.ViewConfiguration;
27
28/**
29 * This keeps track of the touch state throughout the current touch gesture.
30 */
31public class PipTouchState {
32
33 private ViewConfiguration mViewConfig;
34
35 private VelocityTracker mVelocityTracker;
36 private final PointF mDownTouch = new PointF();
37 private final PointF mDownDelta = new PointF();
38 private final PointF mLastTouch = new PointF();
39 private final PointF mLastDelta = new PointF();
40 private final PointF mVelocity = new PointF();
41 private boolean mIsDragging = false;
42 private boolean mStartedDragging = false;
Winson Chungd5a01592016-11-11 16:25:04 -080043 private boolean mAllowDraggingOffscreen = false;
Winson Chungfa7053782016-11-08 15:45:10 -080044 private int mActivePointerId;
45
46 public PipTouchState(ViewConfiguration viewConfig) {
47 mViewConfig = viewConfig;
48 }
49
50 /**
51 * Processess a given touch event and updates the state.
52 */
53 public void onTouchEvent(MotionEvent ev) {
54 switch (ev.getAction()) {
55 case MotionEvent.ACTION_DOWN: {
56 // Initialize the velocity tracker
57 initOrResetVelocityTracker();
58 mActivePointerId = ev.getPointerId(0);
59 mLastTouch.set(ev.getX(), ev.getY());
60 mDownTouch.set(mLastTouch);
61 mIsDragging = false;
62 mStartedDragging = false;
Winson Chungd5a01592016-11-11 16:25:04 -080063 mAllowDraggingOffscreen = true;
Winson Chungfa7053782016-11-08 15:45:10 -080064 break;
65 }
66 case MotionEvent.ACTION_MOVE: {
67 // Update the velocity tracker
68 mVelocityTracker.addMovement(ev);
69 int pointerIndex = ev.findPointerIndex(mActivePointerId);
70 float x = ev.getX(pointerIndex);
71 float y = ev.getY(pointerIndex);
72 mLastDelta.set(x - mLastTouch.x, y - mLastTouch.y);
73 mDownDelta.set(x - mDownTouch.x, y - mDownTouch.y);
74
75 boolean hasMovedBeyondTap = mDownDelta.length() > mViewConfig.getScaledTouchSlop();
76 if (!mIsDragging) {
77 if (hasMovedBeyondTap) {
78 mIsDragging = true;
79 mStartedDragging = true;
80 }
81 } else {
82 mStartedDragging = false;
83 }
84 mLastTouch.set(x, y);
85 break;
86 }
87 case MotionEvent.ACTION_POINTER_UP: {
88 // Update the velocity tracker
89 mVelocityTracker.addMovement(ev);
90
91 int pointerIndex = ev.getActionIndex();
92 int pointerId = ev.getPointerId(pointerIndex);
93 if (pointerId == mActivePointerId) {
94 // Select a new active pointer id and reset the movement state
95 final int newPointerIndex = (pointerIndex == 0) ? 1 : 0;
96 mActivePointerId = ev.getPointerId(newPointerIndex);
97 mLastTouch.set(ev.getX(newPointerIndex), ev.getY(newPointerIndex));
98 }
99 break;
100 }
101 case MotionEvent.ACTION_UP: {
102 // Update the velocity tracker
103 mVelocityTracker.addMovement(ev);
104 mVelocityTracker.computeCurrentVelocity(1000,
105 mViewConfig.getScaledMaximumFlingVelocity());
106 mVelocity.set(mVelocityTracker.getXVelocity(), mVelocityTracker.getYVelocity());
107
108 int pointerIndex = ev.findPointerIndex(mActivePointerId);
109 mLastTouch.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
110
111 // Fall through to clean up
112 }
113 case MotionEvent.ACTION_CANCEL: {
114 recycleVelocityTracker();
115 break;
116 }
117 }
118 }
119
120 /**
121 * @return the velocity of the active touch pointer at the point it is lifted off the screen.
122 */
123 public PointF getVelocity() {
124 return mVelocity;
125 }
126
127 /**
128 * @return the last touch position of the active pointer.
129 */
130 public PointF getLastTouchPosition() {
131 return mLastTouch;
132 }
133
134 /**
135 * @return the movement delta between the last handled touch event and the previous touch
136 * position.
137 */
138 public PointF getLastTouchDelta() {
139 return mLastDelta;
140 }
141
142 /**
143 * @return the movement delta between the last handled touch event and the down touch
144 * position.
145 */
146 public PointF getDownTouchDelta() {
147 return mDownDelta;
148 }
149
150 /**
151 * @return whether the user has started dragging.
152 */
153 public boolean isDragging() {
154 return mIsDragging;
155 }
156
157 /**
158 * @return whether the user has started dragging just in the last handled touch event.
159 */
160 public boolean startedDragging() {
161 return mStartedDragging;
162 }
163
Winson Chungd5a01592016-11-11 16:25:04 -0800164 /**
165 * Disallows dragging offscreen for the duration of the current gesture.
166 */
167 public void setDisallowDraggingOffscreen() {
168 mAllowDraggingOffscreen = false;
169 }
170
171 /**
172 * @return whether dragging offscreen is allowed during this gesture.
173 */
174 public boolean allowDraggingOffscreen() {
175 return mAllowDraggingOffscreen;
176 }
177
Winson Chungfa7053782016-11-08 15:45:10 -0800178 private void initOrResetVelocityTracker() {
179 if (mVelocityTracker == null) {
180 mVelocityTracker = VelocityTracker.obtain();
181 } else {
182 mVelocityTracker.clear();
183 }
184 }
185
186 private void recycleVelocityTracker() {
187 if (mVelocityTracker != null) {
188 mVelocityTracker.recycle();
189 mVelocityTracker = null;
190 }
191 }
192}