blob: 48c5b46c34d75d754b3e21ea54a88d800fbafbb5 [file] [log] [blame]
Winson Chungcdbbb7e2014-06-24 12:11:49 -07001/*
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
17package com.android.systemui.recents.views;
18
19import android.content.Context;
Winson Chungd213a1e2014-10-02 11:18:30 -070020import android.view.InputDevice;
Winson Chungcdbbb7e2014-06-24 12:11:49 -070021import android.view.MotionEvent;
22import android.view.VelocityTracker;
23import android.view.View;
24import android.view.ViewConfiguration;
25import android.view.ViewParent;
Winson Chung5c9f4b92015-06-25 16:16:46 -070026import com.android.internal.logging.MetricsLogger;
Winson2536c7e2015-10-01 15:49:31 -070027import com.android.systemui.R;
Winson Chungcdbbb7e2014-06-24 12:11:49 -070028import com.android.systemui.recents.Constants;
James Cook4bd79b72015-03-17 07:33:28 -070029import com.android.systemui.recents.Recents;
Winson2536c7e2015-10-01 15:49:31 -070030import com.android.systemui.recents.events.EventBus;
31import com.android.systemui.recents.events.ui.DismissTaskEvent;
Winson Chungcdbbb7e2014-06-24 12:11:49 -070032
Winson Chung6ac8bd62015-01-07 16:38:35 -080033import java.util.List;
34
Winson Chungcdbbb7e2014-06-24 12:11:49 -070035/* Handles touch events for a TaskStackView. */
36class TaskStackViewTouchHandler implements SwipeHelper.Callback {
37 static int INACTIVE_POINTER_ID = -1;
38
Winson35f30502015-09-28 11:24:36 -070039 Context mContext;
Winson Chungcdbbb7e2014-06-24 12:11:49 -070040 TaskStackView mSv;
Winson Chung012ef362014-07-31 18:36:25 -070041 TaskStackViewScroller mScroller;
Winson Chungcdbbb7e2014-06-24 12:11:49 -070042 VelocityTracker mVelocityTracker;
43
44 boolean mIsScrolling;
45
Winson Chung012ef362014-07-31 18:36:25 -070046 float mInitialP;
47 float mLastP;
48 float mTotalPMotion;
Winson Chungcdbbb7e2014-06-24 12:11:49 -070049 int mInitialMotionX, mInitialMotionY;
50 int mLastMotionX, mLastMotionY;
51 int mActivePointerId = INACTIVE_POINTER_ID;
52 TaskView mActiveTaskView = null;
53
Winson Chungcdbbb7e2014-06-24 12:11:49 -070054 int mMinimumVelocity;
55 int mMaximumVelocity;
56 // The scroll touch slop is used to calculate when we start scrolling
57 int mScrollTouchSlop;
58 // The page touch slop is used to calculate when we start swiping
59 float mPagingTouchSlop;
James Cook4bd79b72015-03-17 07:33:28 -070060 // Used to calculate when a tap is outside a task view rectangle.
61 final int mWindowTouchSlop;
Winson Chungcdbbb7e2014-06-24 12:11:49 -070062
63 SwipeHelper mSwipeHelper;
64 boolean mInterceptedBySwipeHelper;
65
Winson Chungebfc6982014-08-26 12:25:34 -070066 public TaskStackViewTouchHandler(Context context, TaskStackView sv,
Winson35f30502015-09-28 11:24:36 -070067 TaskStackViewScroller scroller) {
68 mContext = context;
Winson Chungcdbbb7e2014-06-24 12:11:49 -070069 ViewConfiguration configuration = ViewConfiguration.get(context);
70 mMinimumVelocity = configuration.getScaledMinimumFlingVelocity();
71 mMaximumVelocity = configuration.getScaledMaximumFlingVelocity();
72 mScrollTouchSlop = configuration.getScaledTouchSlop();
73 mPagingTouchSlop = configuration.getScaledPagingTouchSlop();
James Cook4bd79b72015-03-17 07:33:28 -070074 mWindowTouchSlop = configuration.getScaledWindowTouchSlop();
Winson Chungcdbbb7e2014-06-24 12:11:49 -070075 mSv = sv;
Winson Chung012ef362014-07-31 18:36:25 -070076 mScroller = scroller;
Winson Chungcdbbb7e2014-06-24 12:11:49 -070077
78 float densityScale = context.getResources().getDisplayMetrics().density;
Winson35f30502015-09-28 11:24:36 -070079 mSwipeHelper = new SwipeHelper(context, SwipeHelper.X, this, densityScale, mPagingTouchSlop);
Winson Chungcdbbb7e2014-06-24 12:11:49 -070080 mSwipeHelper.setMinAlpha(1f);
81 }
82
83 /** Velocity tracker helpers */
84 void initOrResetVelocityTracker() {
85 if (mVelocityTracker == null) {
86 mVelocityTracker = VelocityTracker.obtain();
87 } else {
88 mVelocityTracker.clear();
89 }
90 }
91 void initVelocityTrackerIfNotExists() {
92 if (mVelocityTracker == null) {
93 mVelocityTracker = VelocityTracker.obtain();
94 }
95 }
96 void recycleVelocityTracker() {
97 if (mVelocityTracker != null) {
98 mVelocityTracker.recycle();
99 mVelocityTracker = null;
100 }
101 }
102
103 /** Returns the view at the specified coordinates */
104 TaskView findViewAtPoint(int x, int y) {
Winson Chung6ac8bd62015-01-07 16:38:35 -0800105 List<TaskView> taskViews = mSv.getTaskViews();
106 int taskViewCount = taskViews.size();
107 for (int i = taskViewCount - 1; i >= 0; i--) {
108 TaskView tv = taskViews.get(i);
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700109 if (tv.getVisibility() == View.VISIBLE) {
110 if (mSv.isTransformedTouchPointInView(x, y, tv)) {
111 return tv;
112 }
113 }
114 }
115 return null;
116 }
117
Winson Chung012ef362014-07-31 18:36:25 -0700118 /** Constructs a simulated motion event for the current stack scroll. */
119 MotionEvent createMotionEventForStackScroll(MotionEvent ev) {
120 MotionEvent pev = MotionEvent.obtainNoHistory(ev);
121 pev.setLocation(0, mScroller.progressToScrollRange(mScroller.getStackScroll()));
122 return pev;
123 }
124
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700125 /** Touch preprocessing for handling below */
126 public boolean onInterceptTouchEvent(MotionEvent ev) {
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700127 // Return early if we have no children
Winson Chung6ac8bd62015-01-07 16:38:35 -0800128 boolean hasTaskViews = (mSv.getTaskViews().size() > 0);
129 if (!hasTaskViews) {
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700130 return false;
131 }
132
133 // Pass through to swipe helper if we are swiping
134 mInterceptedBySwipeHelper = mSwipeHelper.onInterceptTouchEvent(ev);
135 if (mInterceptedBySwipeHelper) {
136 return true;
137 }
138
Winson Chung012ef362014-07-31 18:36:25 -0700139 boolean wasScrolling = mScroller.isScrolling() ||
140 (mScroller.mScrollAnimator != null && mScroller.mScrollAnimator.isRunning());
Winson147ecaf2015-09-16 16:49:55 -0700141 int action = ev.getAction();
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700142 switch (action & MotionEvent.ACTION_MASK) {
143 case MotionEvent.ACTION_DOWN: {
144 // Save the touch down info
145 mInitialMotionX = mLastMotionX = (int) ev.getX();
146 mInitialMotionY = mLastMotionY = (int) ev.getY();
Winson Chung012ef362014-07-31 18:36:25 -0700147 mInitialP = mLastP = mSv.mLayoutAlgorithm.screenYToCurveProgress(mLastMotionY);
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700148 mActivePointerId = ev.getPointerId(0);
149 mActiveTaskView = findViewAtPoint(mLastMotionX, mLastMotionY);
150 // Stop the current scroll if it is still flinging
Winson Chung012ef362014-07-31 18:36:25 -0700151 mScroller.stopScroller();
152 mScroller.stopBoundScrollAnimation();
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700153 // Initialize the velocity tracker
154 initOrResetVelocityTracker();
Winson Chung012ef362014-07-31 18:36:25 -0700155 mVelocityTracker.addMovement(createMotionEventForStackScroll(ev));
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700156 break;
157 }
158 case MotionEvent.ACTION_MOVE: {
159 if (mActivePointerId == INACTIVE_POINTER_ID) break;
160
Justin Harrison31d98372014-12-04 20:05:21 +0000161 // Initialize the velocity tracker if necessary
162 initVelocityTrackerIfNotExists();
163 mVelocityTracker.addMovement(createMotionEventForStackScroll(ev));
164
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700165 int activePointerIndex = ev.findPointerIndex(mActivePointerId);
166 int y = (int) ev.getY(activePointerIndex);
167 int x = (int) ev.getX(activePointerIndex);
168 if (Math.abs(y - mInitialMotionY) > mScrollTouchSlop) {
169 // Save the touch move info
170 mIsScrolling = true;
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700171 // Disallow parents from intercepting touch events
172 final ViewParent parent = mSv.getParent();
173 if (parent != null) {
174 parent.requestDisallowInterceptTouchEvent(true);
175 }
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700176 }
177
178 mLastMotionX = x;
179 mLastMotionY = y;
Winson Chung012ef362014-07-31 18:36:25 -0700180 mLastP = mSv.mLayoutAlgorithm.screenYToCurveProgress(mLastMotionY);
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700181 break;
182 }
183 case MotionEvent.ACTION_CANCEL:
184 case MotionEvent.ACTION_UP: {
185 // Animate the scroll back if we've cancelled
Winson Chung012ef362014-07-31 18:36:25 -0700186 mScroller.animateBoundScroll();
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700187 // Reset the drag state and the velocity tracker
188 mIsScrolling = false;
189 mActivePointerId = INACTIVE_POINTER_ID;
190 mActiveTaskView = null;
Winson Chung012ef362014-07-31 18:36:25 -0700191 mTotalPMotion = 0;
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700192 recycleVelocityTracker();
193 break;
194 }
195 }
196
197 return wasScrolling || mIsScrolling;
198 }
199
200 /** Handles touch events once we have intercepted them */
201 public boolean onTouchEvent(MotionEvent ev) {
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700202 // Short circuit if we have no children
Winson Chung6ac8bd62015-01-07 16:38:35 -0800203 boolean hasTaskViews = (mSv.getTaskViews().size() > 0);
204 if (!hasTaskViews) {
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700205 return false;
206 }
207
208 // Pass through to swipe helper if we are swiping
209 if (mInterceptedBySwipeHelper && mSwipeHelper.onTouchEvent(ev)) {
210 return true;
211 }
212
213 // Update the velocity tracker
214 initVelocityTrackerIfNotExists();
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700215
Winson147ecaf2015-09-16 16:49:55 -0700216 int action = ev.getAction();
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700217 switch (action & MotionEvent.ACTION_MASK) {
218 case MotionEvent.ACTION_DOWN: {
219 // Save the touch down info
220 mInitialMotionX = mLastMotionX = (int) ev.getX();
221 mInitialMotionY = mLastMotionY = (int) ev.getY();
Winson Chung012ef362014-07-31 18:36:25 -0700222 mInitialP = mLastP = mSv.mLayoutAlgorithm.screenYToCurveProgress(mLastMotionY);
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700223 mActivePointerId = ev.getPointerId(0);
224 mActiveTaskView = findViewAtPoint(mLastMotionX, mLastMotionY);
225 // Stop the current scroll if it is still flinging
Winson Chung012ef362014-07-31 18:36:25 -0700226 mScroller.stopScroller();
227 mScroller.stopBoundScrollAnimation();
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700228 // Initialize the velocity tracker
229 initOrResetVelocityTracker();
Winson Chung012ef362014-07-31 18:36:25 -0700230 mVelocityTracker.addMovement(createMotionEventForStackScroll(ev));
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700231 // Disallow parents from intercepting touch events
232 final ViewParent parent = mSv.getParent();
233 if (parent != null) {
234 parent.requestDisallowInterceptTouchEvent(true);
235 }
236 break;
237 }
238 case MotionEvent.ACTION_POINTER_DOWN: {
239 final int index = ev.getActionIndex();
240 mActivePointerId = ev.getPointerId(index);
241 mLastMotionX = (int) ev.getX(index);
242 mLastMotionY = (int) ev.getY(index);
Winson Chung012ef362014-07-31 18:36:25 -0700243 mLastP = mSv.mLayoutAlgorithm.screenYToCurveProgress(mLastMotionY);
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700244 break;
245 }
246 case MotionEvent.ACTION_MOVE: {
247 if (mActivePointerId == INACTIVE_POINTER_ID) break;
248
Justin Harrison31d98372014-12-04 20:05:21 +0000249 mVelocityTracker.addMovement(createMotionEventForStackScroll(ev));
250
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700251 int activePointerIndex = ev.findPointerIndex(mActivePointerId);
252 int x = (int) ev.getX(activePointerIndex);
253 int y = (int) ev.getY(activePointerIndex);
254 int yTotal = Math.abs(y - mInitialMotionY);
Winson Chung012ef362014-07-31 18:36:25 -0700255 float curP = mSv.mLayoutAlgorithm.screenYToCurveProgress(y);
256 float deltaP = mLastP - curP;
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700257 if (!mIsScrolling) {
258 if (yTotal > mScrollTouchSlop) {
259 mIsScrolling = true;
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700260 // Disallow parents from intercepting touch events
261 final ViewParent parent = mSv.getParent();
262 if (parent != null) {
263 parent.requestDisallowInterceptTouchEvent(true);
264 }
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700265 }
266 }
267 if (mIsScrolling) {
Winson Chung012ef362014-07-31 18:36:25 -0700268 float curStackScroll = mScroller.getStackScroll();
269 float overScrollAmount = mScroller.getScrollAmountOutOfBounds(curStackScroll + deltaP);
270 if (Float.compare(overScrollAmount, 0f) != 0) {
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700271 // Bound the overscroll to a fixed amount, and inversely scale the y-movement
272 // relative to how close we are to the max overscroll
Winson35f30502015-09-28 11:24:36 -0700273 float maxOverScroll = mContext.getResources().getFloat(
274 R.dimen.recents_stack_overscroll_percentage);
Winson Chung012ef362014-07-31 18:36:25 -0700275 deltaP *= (1f - (Math.min(maxOverScroll, overScrollAmount)
276 / maxOverScroll));
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700277 }
Winson Chung012ef362014-07-31 18:36:25 -0700278 mScroller.setStackScroll(curStackScroll + deltaP);
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700279 }
280 mLastMotionX = x;
281 mLastMotionY = y;
Winson Chung012ef362014-07-31 18:36:25 -0700282 mLastP = mSv.mLayoutAlgorithm.screenYToCurveProgress(mLastMotionY);
283 mTotalPMotion += Math.abs(deltaP);
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700284 break;
285 }
286 case MotionEvent.ACTION_UP: {
Winson Chung2cf8b222015-01-20 11:44:05 -0800287 mVelocityTracker.computeCurrentVelocity(1000, mMaximumVelocity);
288 int velocity = (int) mVelocityTracker.getYVelocity(mActivePointerId);
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700289 if (mIsScrolling && (Math.abs(velocity) > mMinimumVelocity)) {
Winson Chung2cf8b222015-01-20 11:44:05 -0800290 float overscrollRangePct = Math.abs((float) velocity / mMaximumVelocity);
291 int overscrollRange = (int) (Math.min(1f, overscrollRangePct) *
292 (Constants.Values.TaskStackView.TaskStackMaxOverscrollRange -
293 Constants.Values.TaskStackView.TaskStackMinOverscrollRange));
294 mScroller.mScroller.fling(0,
295 mScroller.progressToScrollRange(mScroller.getStackScroll()),
Winson Chung012ef362014-07-31 18:36:25 -0700296 0, velocity,
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700297 0, 0,
Winson Chung012ef362014-07-31 18:36:25 -0700298 mScroller.progressToScrollRange(mSv.mLayoutAlgorithm.mMinScrollP),
299 mScroller.progressToScrollRange(mSv.mLayoutAlgorithm.mMaxScrollP),
Winson Chung2cf8b222015-01-20 11:44:05 -0800300 0, Constants.Values.TaskStackView.TaskStackMinOverscrollRange +
301 overscrollRange);
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700302 // Invalidate to kick off computeScroll
Winson Chung012ef362014-07-31 18:36:25 -0700303 mSv.invalidate();
Winson Chungfce23742015-07-30 17:33:31 -0700304 } else if (mIsScrolling && mScroller.isScrollOutOfBounds()) {
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700305 // Animate the scroll back into bounds
Winson Chung012ef362014-07-31 18:36:25 -0700306 mScroller.animateBoundScroll();
James Cook4bd79b72015-03-17 07:33:28 -0700307 } else if (mActiveTaskView == null) {
308 // This tap didn't start on a task.
309 maybeHideRecentsFromBackgroundTap((int) ev.getX(), (int) ev.getY());
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700310 }
311
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700312 mActivePointerId = INACTIVE_POINTER_ID;
313 mIsScrolling = false;
Winson Chung012ef362014-07-31 18:36:25 -0700314 mTotalPMotion = 0;
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700315 recycleVelocityTracker();
316 break;
317 }
318 case MotionEvent.ACTION_POINTER_UP: {
319 int pointerIndex = ev.getActionIndex();
320 int pointerId = ev.getPointerId(pointerIndex);
321 if (pointerId == mActivePointerId) {
322 // Select a new active pointer id and reset the motion state
323 final int newPointerIndex = (pointerIndex == 0) ? 1 : 0;
324 mActivePointerId = ev.getPointerId(newPointerIndex);
325 mLastMotionX = (int) ev.getX(newPointerIndex);
326 mLastMotionY = (int) ev.getY(newPointerIndex);
Winson Chung012ef362014-07-31 18:36:25 -0700327 mLastP = mSv.mLayoutAlgorithm.screenYToCurveProgress(mLastMotionY);
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700328 mVelocityTracker.clear();
329 }
330 break;
331 }
332 case MotionEvent.ACTION_CANCEL: {
Winson Chung012ef362014-07-31 18:36:25 -0700333 if (mScroller.isScrollOutOfBounds()) {
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700334 // Animate the scroll back into bounds
Winson Chung012ef362014-07-31 18:36:25 -0700335 mScroller.animateBoundScroll();
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700336 }
337 mActivePointerId = INACTIVE_POINTER_ID;
338 mIsScrolling = false;
Winson Chung012ef362014-07-31 18:36:25 -0700339 mTotalPMotion = 0;
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700340 recycleVelocityTracker();
341 break;
342 }
343 }
344 return true;
345 }
346
James Cook4bd79b72015-03-17 07:33:28 -0700347 /** Hides recents if the up event at (x, y) is a tap on the background area. */
348 void maybeHideRecentsFromBackgroundTap(int x, int y) {
349 // Ignore the up event if it's too far from its start position. The user might have been
350 // trying to scroll or swipe.
351 int dx = Math.abs(mInitialMotionX - x);
352 int dy = Math.abs(mInitialMotionY - y);
353 if (dx > mScrollTouchSlop || dy > mScrollTouchSlop) {
354 return;
355 }
356
357 // Shift the tap position toward the center of the task stack and check to see if it would
358 // have hit a view. The user might have tried to tap on a task and missed slightly.
359 int shiftedX = x;
Winson147ecaf2015-09-16 16:49:55 -0700360 if (x > (mSv.getRight() - mSv.getLeft()) / 2) {
James Cook4bd79b72015-03-17 07:33:28 -0700361 shiftedX -= mWindowTouchSlop;
362 } else {
363 shiftedX += mWindowTouchSlop;
364 }
365 if (findViewAtPoint(shiftedX, y) != null) {
366 return;
367 }
368
369 // The user intentionally tapped on the background, which is like a tap on the "desktop".
370 // Hide recents and transition to the launcher.
371 Recents recents = Recents.getInstanceAndStartIfNeeded(mSv.getContext());
372 recents.hideRecents(false /* altTab */, true /* homeKey */);
373 }
374
Winson Chungd213a1e2014-10-02 11:18:30 -0700375 /** Handles generic motion events */
376 public boolean onGenericMotionEvent(MotionEvent ev) {
377 if ((ev.getSource() & InputDevice.SOURCE_CLASS_POINTER) ==
378 InputDevice.SOURCE_CLASS_POINTER) {
379 int action = ev.getAction();
380 switch (action & MotionEvent.ACTION_MASK) {
381 case MotionEvent.ACTION_SCROLL:
382 // Find the front most task and scroll the next task to the front
383 float vScroll = ev.getAxisValue(MotionEvent.AXIS_VSCROLL);
384 if (vScroll > 0) {
Winson Chung83ea6f72015-06-17 13:00:23 -0700385 if (mSv.ensureFocusedTask(true)) {
Winson Chungd213a1e2014-10-02 11:18:30 -0700386 mSv.focusNextTask(true, false);
387 }
388 } else {
Winson Chung83ea6f72015-06-17 13:00:23 -0700389 if (mSv.ensureFocusedTask(true)) {
Winson Chungd213a1e2014-10-02 11:18:30 -0700390 mSv.focusNextTask(false, false);
391 }
392 }
393 return true;
394 }
395 }
396 return false;
397 }
398
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700399 /**** SwipeHelper Implementation ****/
400
401 @Override
402 public View getChildAtPosition(MotionEvent ev) {
403 return findViewAtPoint((int) ev.getX(), (int) ev.getY());
404 }
405
406 @Override
407 public boolean canChildBeDismissed(View v) {
408 return true;
409 }
410
411 @Override
412 public void onBeginDrag(View v) {
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700413 TaskView tv = (TaskView) v;
Winson Chung8eaeb7d2014-06-25 15:10:59 -0700414 // Disable clipping with the stack while we are swiping
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700415 tv.setClipViewInStack(false);
Winson Chung8eaeb7d2014-06-25 15:10:59 -0700416 // Disallow touch events from this task view
Winson Chung1f24c7e2014-07-11 17:06:48 -0700417 tv.setTouchEnabled(false);
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700418 // Disallow parents from intercepting touch events
419 final ViewParent parent = mSv.getParent();
420 if (parent != null) {
421 parent.requestDisallowInterceptTouchEvent(true);
422 }
Winson Chung6ac8bd62015-01-07 16:38:35 -0800423 // Fade out the dismiss button
424 mSv.hideDismissAllButton(null);
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700425 }
426
427 @Override
428 public void onSwipeChanged(View v, float delta) {
429 // Do nothing
430 }
431
432 @Override
433 public void onChildDismissed(View v) {
434 TaskView tv = (TaskView) v;
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700435 // Re-enable clipping with the stack (we will reuse this view)
436 tv.setClipViewInStack(true);
Winson Chung3e3365b2014-07-17 18:39:02 -0700437 // Re-enable touch events from this task view
438 tv.setTouchEnabled(true);
Winson Chung8eaeb7d2014-06-25 15:10:59 -0700439 // Remove the task view from the stack
Winson2536c7e2015-10-01 15:49:31 -0700440 EventBus.getDefault().send(new DismissTaskEvent(tv.getTask(), tv));
Winson Chung5c9f4b92015-06-25 16:16:46 -0700441 // Keep track of deletions by keyboard
442 MetricsLogger.histogram(tv.getContext(), "overview_task_dismissed_source",
443 Constants.Metrics.DismissSourceSwipeGesture);
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700444 }
445
446 @Override
447 public void onSnapBackCompleted(View v) {
Winson Chung8eaeb7d2014-06-25 15:10:59 -0700448 TaskView tv = (TaskView) v;
Winson Chung8eaeb7d2014-06-25 15:10:59 -0700449 // Re-enable clipping with the stack
450 tv.setClipViewInStack(true);
451 // Re-enable touch events from this task view
Winson Chung1f24c7e2014-07-11 17:06:48 -0700452 tv.setTouchEnabled(true);
Winson Chung6ac8bd62015-01-07 16:38:35 -0800453 // Restore the dismiss button
454 mSv.showDismissAllButton();
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700455 }
Winson Chung7aceb9a2014-07-03 13:38:01 -0700456
457 @Override
458 public void onDragCancelled(View v) {
459 // Do nothing
460 }
Winson Chungcdbbb7e2014-06-24 12:11:49 -0700461}