Handle swipe down on taskbar to stash
- Moved all touch-to-stash logic to new TaskbarStashViaTouchController
(handles both tap outside to stash instantly as well as swipe down
inside to stash after letting go)
- This is a TouchController on TaskbarDragLayer, so it intercepts
touches from TaskbarView before icons can be dragged during swipe down
Test: swipe up to invoke transient taskbar in an app, swipe down or
touch outside to stash
Flag: ENABLE_TRANSIENT_TASKBAR=true
Fixes: 246631710
Change-Id: I5cf64848bba34ad32fcc80a93fb4f79ebd2c10a7
diff --git a/quickstep/res/values-sw720dp/dimens.xml b/quickstep/res/values-sw720dp/dimens.xml
index f093185..0832a91 100644
--- a/quickstep/res/values-sw720dp/dimens.xml
+++ b/quickstep/res/values-sw720dp/dimens.xml
@@ -43,7 +43,7 @@
<dimen name="transient_taskbar_icon_size">52dp</dimen>
<!-- Taskbar swipe up thresholds -->
- <dimen name="taskbar_nav_threshold">30dp</dimen>
+ <dimen name="taskbar_from_nav_threshold">30dp</dimen>
<dimen name="taskbar_app_window_threshold">100dp</dimen>
<dimen name="taskbar_home_overview_threshold">180dp</dimen>
<dimen name="taskbar_catch_up_threshold">300dp</dimen>
diff --git a/quickstep/res/values/dimens.xml b/quickstep/res/values/dimens.xml
index 225bdcc..3f4f527 100644
--- a/quickstep/res/values/dimens.xml
+++ b/quickstep/res/values/dimens.xml
@@ -303,10 +303,12 @@
<!-- An additional touch slop to prevent x-axis movement during the swipe up to show taskbar -->
<dimen name="transient_taskbar_clamped_offset_bound">16dp</dimen>
<!-- Taskbar swipe up thresholds -->
- <dimen name="taskbar_nav_threshold">40dp</dimen>
+ <dimen name="taskbar_from_nav_threshold">40dp</dimen>
<dimen name="taskbar_app_window_threshold">88dp</dimen>
<dimen name="taskbar_home_overview_threshold">156dp</dimen>
<dimen name="taskbar_catch_up_threshold">264dp</dimen>
+ <!-- Taskbar swipe down threshold -->
+ <dimen name="taskbar_to_nav_threshold">24dp</dimen>
<!-- Taskbar 3 button spacing -->
<dimen name="taskbar_button_space_inbetween">24dp</dimen>
diff --git a/quickstep/src/com/android/launcher3/taskbar/StashedHandleView.java b/quickstep/src/com/android/launcher3/taskbar/StashedHandleView.java
index 6db5839..5eec6a4 100644
--- a/quickstep/src/com/android/launcher3/taskbar/StashedHandleView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/StashedHandleView.java
@@ -69,6 +69,10 @@
*/
public void updateSampledRegion(Rect stashedHandleBounds) {
getLocationOnScreen(mTmpArr);
+ // Translations are temporary due to animations, remove them for the purpose of determining
+ // the final region we want sampled.
+ mTmpArr[0] -= Math.round(getTranslationX());
+ mTmpArr[1] -= Math.round(getTranslationY());
mSampledRegion.set(stashedHandleBounds);
mSampledRegion.offset(mTmpArr[0], mTmpArr[1]);
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
index 58d6244..6cc6a84 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayer.java
@@ -117,22 +117,6 @@
}
@Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- if (mControllerCallbacks != null) {
- mControllerCallbacks.tryStashBasedOnMotionEvent(ev);
- }
- return super.onInterceptTouchEvent(ev);
- }
-
- @Override
- public boolean onTouchEvent(MotionEvent ev) {
- if (mControllerCallbacks != null) {
- mControllerCallbacks.tryStashBasedOnMotionEvent(ev);
- }
- return super.onTouchEvent(ev);
- }
-
- @Override
public void onViewRemoved(View child) {
super.onViewRemoved(child);
if (mControllerCallbacks != null) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
index 7c3d14d..56be48e 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarDragLayerController.java
@@ -18,15 +18,12 @@
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
-import android.view.MotionEvent;
import android.view.ViewTreeObserver;
import com.android.launcher3.DeviceProfile;
import com.android.launcher3.R;
import com.android.launcher3.anim.AnimatedFloat;
-import com.android.launcher3.testing.shared.ResourceUtils;
import com.android.launcher3.util.DimensionUtils;
-import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.TouchController;
import java.io.PrintWriter;
@@ -40,7 +37,6 @@
private final TaskbarActivityContext mActivity;
private final TaskbarDragLayer mTaskbarDragLayer;
private final int mFolderMargin;
- private float mGestureHeightYThreshold;
// Alpha properties for taskbar background.
private final AnimatedFloat mBgTaskbar = new AnimatedFloat(this::updateBackgroundAlpha);
@@ -59,6 +55,7 @@
// Initialized in init.
private TaskbarControllers mControllers;
+ private TaskbarStashViaTouchController mTaskbarStashViaTouchController;
private AnimatedFloat mOnBackgroundNavButtonColorIntensity;
private float mLastSetBackgroundAlpha;
@@ -69,11 +66,11 @@
mTaskbarDragLayer = taskbarDragLayer;
final Resources resources = mTaskbarDragLayer.getResources();
mFolderMargin = resources.getDimensionPixelSize(R.dimen.taskbar_folder_margin);
- updateGestureHeight();
}
public void init(TaskbarControllers controllers) {
mControllers = controllers;
+ mTaskbarStashViaTouchController = new TaskbarStashViaTouchController(mControllers);
mTaskbarDragLayer.init(new TaskbarDragLayerCallbacks());
mOnBackgroundNavButtonColorIntensity = mControllers.navbarButtonsViewController
@@ -130,17 +127,11 @@
return mBgOffset;
}
- private void updateGestureHeight() {
- int gestureHeight = ResourceUtils.getNavbarSize(ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE,
- mActivity.getResources());
- mGestureHeightYThreshold = mActivity.getDeviceProfile().heightPx - gestureHeight;
- }
-
/**
* Make updates when configuration changes.
*/
public void onConfigurationChanged() {
- updateGestureHeight();
+ mTaskbarStashViaTouchController.updateGestureHeight();
}
private void updateBackgroundAlpha() {
@@ -206,8 +197,6 @@
*/
public class TaskbarDragLayerCallbacks {
- private final int[] mTempOutLocation = new int[2];
-
/**
* Called to update the touchable insets.
* @see ViewTreeObserver.InternalInsetsInfo#setTouchableInsets(int)
@@ -217,37 +206,6 @@
}
/**
- * Listens to TaskbarDragLayer touch events and responds accordingly.
- */
- public void tryStashBasedOnMotionEvent(MotionEvent ev) {
- if (!DisplayController.isTransientTaskbar(mActivity)) {
- return;
- }
- if (mControllers.taskbarStashController.isStashed()) {
- return;
- }
-
- boolean stashTaskbar = false;
-
- MotionEvent screenCoordinates = MotionEvent.obtain(ev);
- if (ev.getAction() == MotionEvent.ACTION_OUTSIDE) {
- stashTaskbar = true;
- } else if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- mTaskbarDragLayer.getLocationOnScreen(mTempOutLocation);
- screenCoordinates.offsetLocation(mTempOutLocation[0], mTempOutLocation[1]);
-
- if (!mControllers.taskbarViewController.isEventOverAnyItem(screenCoordinates)
- && screenCoordinates.getY() < mGestureHeightYThreshold) {
- stashTaskbar = true;
- }
- }
-
- if (stashTaskbar) {
- mControllers.taskbarStashController.updateAndAnimateTransientTaskbar(true);
- }
- }
-
- /**
* Called when a child is removed from TaskbarDragLayer.
*/
public void onDragLayerViewRemoved() {
@@ -276,9 +234,12 @@
* Returns touch controllers.
*/
public TouchController[] getTouchControllers() {
- return new TouchController[]{mActivity.getDragController(),
+ return new TouchController[] {
+ mActivity.getDragController(),
mControllers.taskbarForceVisibleImmersiveController,
- mControllers.navbarButtonsViewController.getTouchController()};
+ mControllers.navbarButtonsViewController.getTouchController(),
+ mTaskbarStashViaTouchController,
+ };
}
}
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarStashViaTouchController.kt b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashViaTouchController.kt
new file mode 100644
index 0000000..0e5fa38
--- /dev/null
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarStashViaTouchController.kt
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.android.launcher3.taskbar
+
+import android.view.MotionEvent
+import com.android.launcher3.R
+import com.android.launcher3.Utilities
+import com.android.launcher3.anim.Interpolators.LINEAR
+import com.android.launcher3.testing.shared.ResourceUtils
+import com.android.launcher3.touch.SingleAxisSwipeDetector
+import com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_NEGATIVE
+import com.android.launcher3.touch.SingleAxisSwipeDetector.VERTICAL
+import com.android.launcher3.util.DisplayController
+import com.android.launcher3.util.TouchController
+import com.android.quickstep.inputconsumers.TaskbarStashInputConsumer
+
+/**
+ * A helper [TouchController] for [TaskbarDragLayerController], specifically to handle touch events
+ * to stash Transient Taskbar. There are two cases to handle:
+ * - A touch outside of Transient Taskbar bounds will immediately stash on [MotionEvent.ACTION_DOWN]
+ * or [MotionEvent.ACTION_OUTSIDE].
+ * - Touches inside Transient Taskbar bounds will stash if it is detected as a swipe down gesture.
+ *
+ * Note: touches to *unstash* Taskbar are handled by [TaskbarStashInputConsumer].
+ */
+class TaskbarStashViaTouchController(val controllers: TaskbarControllers) : TouchController {
+
+ private val activity: TaskbarActivityContext = controllers.taskbarActivityContext
+ private val enabled = DisplayController.isTransientTaskbar(activity)
+ private val swipeDownDetector: SingleAxisSwipeDetector
+ private val translationCallback = controllers.taskbarTranslationController.transitionCallback
+ /** Interpolator to apply resistance as user swipes down to the bottom of the screen. */
+ private val displacementInterpolator = LINEAR
+ /** How far we can translate the TaskbarView before it's offscreen. */
+ private val maxVisualDisplacement =
+ activity.resources.getDimensionPixelSize(R.dimen.transient_taskbar_margin).toFloat()
+ /** How far the swipe could go, if user swiped from the very top of TaskbarView. */
+ private val maxTouchDisplacement = maxVisualDisplacement + activity.deviceProfile.taskbarSize
+ private val touchDisplacementToStash =
+ activity.resources.getDimensionPixelSize(R.dimen.taskbar_to_nav_threshold).toFloat()
+
+ /** The height of the system gesture region, so we don't stash when touching down there. */
+ private var gestureHeightYThreshold = 0f
+
+ init {
+ updateGestureHeight()
+ swipeDownDetector = SingleAxisSwipeDetector(activity, createSwipeListener(), VERTICAL)
+ swipeDownDetector.setDetectableScrollConditions(DIRECTION_NEGATIVE, false)
+ }
+
+ fun updateGestureHeight() {
+ if (!enabled) return
+
+ val gestureHeight: Int =
+ ResourceUtils.getNavbarSize(
+ ResourceUtils.NAVBAR_BOTTOM_GESTURE_SIZE,
+ activity.resources
+ )
+ gestureHeightYThreshold = (activity.deviceProfile.heightPx - gestureHeight).toFloat()
+ }
+
+ private fun createSwipeListener() =
+ object : SingleAxisSwipeDetector.Listener {
+ private var lastDisplacement = 0f
+
+ override fun onDragStart(start: Boolean, startDisplacement: Float) {}
+
+ override fun onDrag(displacement: Float): Boolean {
+ lastDisplacement = displacement
+ if (displacement < 0) return false
+ // Apply resistance so that the visual displacement doesn't go beyond the screen.
+ translationCallback.onActionMove(
+ Utilities.mapToRange(
+ displacement,
+ 0f,
+ maxTouchDisplacement,
+ 0f,
+ maxVisualDisplacement,
+ displacementInterpolator
+ )
+ )
+ return false
+ }
+
+ override fun onDragEnd(velocity: Float) {
+ val isFlingDown = swipeDownDetector.isFling(velocity) && velocity > 0
+ val isSignificantDistance = lastDisplacement > touchDisplacementToStash
+ if (isFlingDown || isSignificantDistance) {
+ // Successfully triggered stash.
+ controllers.taskbarStashController.updateAndAnimateTransientTaskbar(true)
+ }
+ translationCallback.onActionEnd()
+ swipeDownDetector.finishedScrolling()
+ }
+ }
+
+ override fun onControllerInterceptTouchEvent(ev: MotionEvent): Boolean {
+ if (!enabled || controllers.taskbarStashController.isStashed) {
+ return false
+ }
+
+ val screenCoordinatesEv = MotionEvent.obtain(ev)
+ screenCoordinatesEv.setLocation(ev.rawX, ev.rawY)
+ if (ev.action == MotionEvent.ACTION_OUTSIDE) {
+ controllers.taskbarStashController.updateAndAnimateTransientTaskbar(true)
+ } else if (controllers.taskbarViewController.isEventOverAnyItem(screenCoordinatesEv)) {
+ swipeDownDetector.onTouchEvent(ev)
+ if (swipeDownDetector.isDraggingState) {
+ return true
+ }
+ } else if (ev.action == MotionEvent.ACTION_DOWN) {
+ if (screenCoordinatesEv.y < gestureHeightYThreshold) {
+ controllers.taskbarStashController.updateAndAnimateTransientTaskbar(true)
+ }
+ }
+ return false
+ }
+
+ override fun onControllerTouchEvent(ev: MotionEvent) = swipeDownDetector.onTouchEvent(ev)
+}
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
index 0116e16..695c3e7 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java
@@ -420,19 +420,9 @@
}
@Override
- public boolean onInterceptTouchEvent(MotionEvent ev) {
- mControllerCallbacks.onInterceptTouchEvent(ev);
- return super.onInterceptTouchEvent(ev);
- }
-
- @Override
public boolean onTouchEvent(MotionEvent event) {
- if (mIconLayoutBounds.left <= event.getX()
- && event.getX() <= mIconLayoutBounds.right
- && !DisplayController.isTransientTaskbar(mActivityContext)) {
- // Don't allow long pressing between icons, or above/below them
- // unless its transient taskbar.
- mControllerCallbacks.clearTouchInProgress();
+ if (mIconLayoutBounds.left <= event.getX() && event.getX() <= mIconLayoutBounds.right) {
+ // Don't allow long pressing between icons, or above/below them.
return true;
}
if (mControllerCallbacks.onTouchEvent(event)) {
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
index 4d92a9e..1560791 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java
@@ -26,8 +26,6 @@
import static com.android.launcher3.anim.Interpolators.LINEAR;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_TASKBAR_ALLAPPS_BUTTON_TAP;
import static com.android.launcher3.taskbar.TaskbarManager.isPhoneMode;
-import static com.android.launcher3.touch.SingleAxisSwipeDetector.DIRECTION_NEGATIVE;
-import static com.android.launcher3.touch.SingleAxisSwipeDetector.VERTICAL;
import static com.android.launcher3.util.MultiPropertyFactory.MULTI_PROPERTY_VALUE;
import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_TASKBAR_ALIGNMENT_ANIM;
import static com.android.launcher3.util.MultiTranslateDelegate.INDEX_TASKBAR_REVEAL_ANIM;
@@ -61,7 +59,6 @@
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.ThemedIconDrawable;
import com.android.launcher3.model.data.ItemInfo;
-import com.android.launcher3.touch.SingleAxisSwipeDetector;
import com.android.launcher3.util.DisplayController;
import com.android.launcher3.util.ItemInfoMatcher;
import com.android.launcher3.util.LauncherBindableItemsContainer;
@@ -115,9 +112,6 @@
private final TaskbarModelCallbacks mModelCallbacks;
- // Captures swipe down action to close transient Taskbar.
- protected @Nullable SingleAxisSwipeDetector mSwipeDownDetector;
-
// Initialized in init.
private TaskbarControllers mControllers;
@@ -154,31 +148,6 @@
colorHSL[2] = TASKBAR_DARK_THEME_ICONS_BACKGROUND_LUMINANCE;
mTaskbarThemedIconsBackgroundColor = ColorUtils.HSLToColor(colorHSL);
}
-
- if (DisplayController.isTransientTaskbar(mActivity)) {
- mSwipeDownDetector = new SingleAxisSwipeDetector(activity,
- new SingleAxisSwipeDetector.Listener() {
- private float mLastDisplacement;
-
- @Override
- public boolean onDrag(float displacement) {
- mLastDisplacement = displacement;
- return false;
- }
-
- @Override
- public void onDragEnd(float velocity) {
- if (mLastDisplacement > 0) {
- mControllers.taskbarStashController
- .updateAndAnimateTransientTaskbar(true);
- }
- }
-
- @Override
- public void onDragStart(boolean start, float startDisplacement) {}
- }, VERTICAL);
- mSwipeDownDetector.setDetectableScrollConditions(DIRECTION_NEGATIVE, false);
- }
mIsRtl = Utilities.isRtl(mTaskbarView.getResources());
}
@@ -649,8 +618,6 @@
private float mDownX, mDownY;
private boolean mCanceledStashHint;
- private boolean mTouchInProgress;
-
public View.OnClickListener getIconOnClickListener() {
return mActivity.getItemOnClickListener();
}
@@ -672,75 +639,39 @@
}
/**
- * Simply listens to all intercept touch events passed to TaskbarView.
- */
- public void onInterceptTouchEvent(MotionEvent ev) {
- if (ev.getAction() == MotionEvent.ACTION_DOWN) {
- mTouchInProgress = true;
- }
-
- if (mTouchInProgress && mSwipeDownDetector != null) {
- mSwipeDownDetector.onTouchEvent(ev);
- }
-
- if (ev.getAction() == MotionEvent.ACTION_UP
- || ev.getAction() == MotionEvent.ACTION_CANCEL) {
- clearTouchInProgress();
- }
- }
-
- /**
* Get the first chance to handle TaskbarView#onTouchEvent, and return whether we want to
* consume the touch so TaskbarView treats it as an ACTION_CANCEL.
+ * TODO(b/270395798): We can remove this entirely once we remove the Transient Taskbar flag.
*/
public boolean onTouchEvent(MotionEvent motionEvent) {
- boolean shouldConsumeTouch = false;
- boolean clearTouchInProgress = false;
-
final float x = motionEvent.getRawX();
final float y = motionEvent.getRawY();
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
- mTouchInProgress = true;
mDownX = x;
mDownY = y;
mControllers.taskbarStashController.startStashHint(/* animateForward = */ true);
mCanceledStashHint = false;
break;
case MotionEvent.ACTION_MOVE:
- if (mTouchInProgress
- && !mCanceledStashHint
+ if (!mCanceledStashHint
&& squaredHypot(mDownX - x, mDownY - y) > mSquaredTouchSlop) {
mControllers.taskbarStashController.startStashHint(
/* animateForward= */ false);
mCanceledStashHint = true;
- shouldConsumeTouch = true;
+ return true;
}
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
- if (mTouchInProgress && !mCanceledStashHint) {
+ if (!mCanceledStashHint) {
mControllers.taskbarStashController.startStashHint(
/* animateForward= */ false);
}
- clearTouchInProgress = true;
break;
}
- if (mTouchInProgress && mSwipeDownDetector != null) {
- mSwipeDownDetector.onTouchEvent(motionEvent);
- }
- if (clearTouchInProgress) {
- clearTouchInProgress();
- }
- return shouldConsumeTouch;
- }
-
- /**
- * Ensures that we do not pass any more touch events to the SwipeDetector.
- */
- public void clearTouchInProgress() {
- mTouchInProgress = false;
+ return false;
}
/**
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
index 1ddb855..87559fb 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarStashInputConsumer.java
@@ -74,7 +74,7 @@
Resources res = context.getResources();
mUnstashArea = res.getDimensionPixelSize(R.dimen.taskbar_unstash_input_area);
- mTaskbarNavThreshold = res.getDimensionPixelSize(R.dimen.taskbar_nav_threshold);
+ mTaskbarNavThreshold = res.getDimensionPixelSize(R.dimen.taskbar_from_nav_threshold);
mTaskbarNavThresholdY = taskbarActivityContext.getDeviceProfile().heightPx
- mTaskbarNavThreshold;
mIsTaskbarAllAppsOpen =
diff --git a/src/com/android/launcher3/views/BaseDragLayer.java b/src/com/android/launcher3/views/BaseDragLayer.java
index 8ff6888..823003c 100644
--- a/src/com/android/launcher3/views/BaseDragLayer.java
+++ b/src/com/android/launcher3/views/BaseDragLayer.java
@@ -18,6 +18,7 @@
import static android.view.MotionEvent.ACTION_CANCEL;
import static android.view.MotionEvent.ACTION_DOWN;
+import static android.view.MotionEvent.ACTION_OUTSIDE;
import static android.view.MotionEvent.ACTION_UP;
import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs;
@@ -260,7 +261,10 @@
mTouchCompleteListener = null;
}
- if (mActiveController != null) {
+ if (mActiveController != null && ev.getAction() != ACTION_OUTSIDE) {
+ // For some reason, once we intercept touches and have an mActiveController, we won't
+ // get onInterceptTouchEvent() for ACTION_OUTSIDE. Thus, we must recalculate a new
+ // TouchController (if any) to handle the ACTION_OUTSIDE here in onTouchEvent() as well.
return mActiveController.onControllerTouchEvent(ev);
} else {
// In case no child view handled the touch event, we may not get onIntercept anymore