Merge "Let the bubble bar handle gestures over the bubble bar." into main
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
index 139e8f0..445b312 100644
--- a/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarUIController.java
@@ -155,7 +155,7 @@
mControllers.taskbarActivityContext.startTranslationSpring();
}
- /*
+ /**
* @param ev MotionEvent in screen coordinates.
* @return Whether any Taskbar item could handle the given MotionEvent if given the chance.
*/
@@ -164,6 +164,14 @@
|| mControllers.navbarButtonsViewController.isEventOverAnyItem(ev);
}
+ /** Checks if the given {@link MotionEvent} is over the bubble bar stash handle. */
+ public boolean isEventOverBubbleBarStashHandle(MotionEvent ev) {
+ return mControllers.bubbleControllers.map(
+ bubbleControllers ->
+ bubbleControllers.bubbleStashController.isEventOverStashHandle(ev))
+ .orElse(false);
+ }
+
/**
* Returns true if icons should be aligned to hotseat in the current transition.
*/
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
index a5ea5a9..09021ed 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashController.java
@@ -22,6 +22,7 @@
import android.animation.AnimatorSet;
import android.annotation.Nullable;
import android.view.InsetsController;
+import android.view.MotionEvent;
import com.android.launcher3.anim.AnimatedFloat;
import com.android.launcher3.taskbar.StashedHandleViewController;
@@ -350,4 +351,9 @@
return mBubblesShowingOnHome ? getBubbleBarTranslationYForHotseat()
: getBubbleBarTranslationYForTaskbar();
}
+
+ /** Checks whether the motion event is over the stash handle. */
+ public boolean isEventOverStashHandle(MotionEvent ev) {
+ return mHandleViewController.isEventOverHandle(ev);
+ }
}
diff --git a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
index fbab595..c998d97 100644
--- a/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
+++ b/quickstep/src/com/android/launcher3/taskbar/bubbles/BubbleStashedHandleViewController.java
@@ -24,6 +24,7 @@
import android.content.res.Resources;
import android.graphics.Outline;
import android.graphics.Rect;
+import android.view.MotionEvent;
import android.view.View;
import android.view.ViewOutlineProvider;
@@ -268,4 +269,22 @@
});
return revealAnim;
}
+
+ /** Checks that the stash handle is visible and that the motion event is within bounds. */
+ public boolean isEventOverHandle(MotionEvent ev) {
+ if (mStashedHandleView.getVisibility() != VISIBLE) {
+ return false;
+ }
+
+ // the bounds of the handle only include the visible part, so we check that the Y coordinate
+ // is anywhere within the stashed taskbar height.
+ int top = mActivity.getDeviceProfile().heightPx - mStashedTaskbarHeight;
+
+ return (int) ev.getRawY() >= top && containsX((int) ev.getRawX());
+ }
+
+ /** Checks if the given x coordinate is within the stashed handle bounds. */
+ public boolean containsX(int x) {
+ return x >= mStashedHandleBounds.left && x <= mStashedHandleBounds.right;
+ }
}
diff --git a/quickstep/src/com/android/quickstep/BaseActivityInterface.java b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
index 3f88139..8925bd6 100644
--- a/quickstep/src/com/android/quickstep/BaseActivityInterface.java
+++ b/quickstep/src/com/android/quickstep/BaseActivityInterface.java
@@ -191,8 +191,11 @@
public abstract boolean allowAllAppsFromOverview();
public boolean deferStartingActivity(RecentsAnimationDeviceState deviceState, MotionEvent ev) {
+ TaskbarUIController controller = getTaskbarController();
+ boolean isEventOverBubbleBarStashHandle =
+ controller != null && controller.isEventOverBubbleBarStashHandle(ev);
return deviceState.isInDeferredGestureRegion(ev) || deviceState.isImeRenderingNavButtons()
- || isTrackpadMultiFingerSwipe(ev);
+ || isTrackpadMultiFingerSwipe(ev) || isEventOverBubbleBarStashHandle;
}
/**
diff --git a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
index 61c2b43..f6a9440 100644
--- a/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
+++ b/quickstep/src/com/android/quickstep/inputconsumers/TaskbarUnstashInputConsumer.java
@@ -15,6 +15,9 @@
*/
package com.android.quickstep.inputconsumers;
+import static android.view.MotionEvent.ACTION_CANCEL;
+import static android.view.MotionEvent.ACTION_MOVE;
+import static android.view.MotionEvent.ACTION_UP;
import static android.view.MotionEvent.INVALID_POINTER_ID;
import static com.android.launcher3.MotionEventsUtils.isTrackpadMotionEvent;
@@ -30,6 +33,7 @@
import android.view.GestureDetector.SimpleOnGestureListener;
import android.view.InputDevice;
import android.view.MotionEvent;
+import android.view.ViewConfiguration;
import androidx.annotation.Nullable;
@@ -68,6 +72,9 @@
private final boolean mIsTaskbarAllAppsOpen;
private boolean mHasPassedTaskbarNavThreshold;
private boolean mIsInBubbleBarArea;
+ private boolean mIsVerticalGestureOverBubbleBar;
+ private boolean mIsPassedBubbleBarSlop;
+ private final int mTouchSlop;
private final PointF mDownPos = new PointF();
private final PointF mLastPos = new PointF();
@@ -91,6 +98,7 @@
mOverviewCommandHelper = overviewCommandHelper;
// TODO(b/270395798): remove this when cleaning up old Persistent Taskbar code.
mSquaredTouchSlop = Utilities.squaredTouchSlop(context);
+ mTouchSlop = ViewConfiguration.get(context).getScaledTouchSlop();
mScreenWidth = taskbarActivityContext.getDeviceProfile().widthPx;
Resources res = context.getResources();
@@ -99,8 +107,7 @@
taskbarActivityContext.getDeviceProfile());
mTaskbarNavThresholdY = taskbarActivityContext.getDeviceProfile().heightPx
- mTaskbarNavThreshold;
- mIsTaskbarAllAppsOpen =
- mTaskbarActivityContext != null && mTaskbarActivityContext.isTaskbarAllAppsOpen();
+ mIsTaskbarAllAppsOpen = mTaskbarActivityContext.isTaskbarAllAppsOpen();
mIsTransientTaskbar = DisplayController.isTransientTaskbar(context);
@@ -132,12 +139,8 @@
if (mState != STATE_ACTIVE) {
boolean isStashedTaskbarHovered = isMouseEvent(ev)
&& isStashedTaskbarHovered((int) ev.getX(), (int) ev.getY());
- if (!isStashedTaskbarHovered) {
- mDelegate.onMotionEvent(ev);
- }
-
// Only show the transient task bar if the touch events are on the screen.
- if (mTaskbarActivityContext != null && !isTrackpadMotionEvent(ev)) {
+ if (!isTrackpadMotionEvent(ev)) {
final float x = ev.getRawX();
final float y = ev.getRawY();
switch (ev.getAction()) {
@@ -193,14 +196,28 @@
}
mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
+ float dX = mLastPos.x - mDownPos.x;
+ float dY = mLastPos.y - mDownPos.y;
+
+ if (!mIsPassedBubbleBarSlop && mIsInBubbleBarArea) {
+ boolean passedSlop =
+ Math.abs(dY) > mTouchSlop || Math.abs(dX) > mTouchSlop;
+ if (passedSlop) {
+ mIsPassedBubbleBarSlop = true;
+ mIsVerticalGestureOverBubbleBar = Math.abs(dY) > Math.abs(dX);
+ if (mIsVerticalGestureOverBubbleBar) {
+ setActive(ev);
+ }
+ }
+ }
+
if (mIsTransientTaskbar) {
- float dY = mLastPos.y - mDownPos.y;
boolean passedTaskbarNavThreshold = dY < 0
&& Math.abs(dY) >= mTaskbarNavThreshold;
if (!mHasPassedTaskbarNavThreshold && passedTaskbarNavThreshold) {
mHasPassedTaskbarNavThreshold = true;
- if (mIsInBubbleBarArea) {
+ if (mIsInBubbleBarArea && mIsVerticalGestureOverBubbleBar) {
mTaskbarActivityContext.onSwipeToOpenBubblebar();
} else {
mTaskbarActivityContext.onSwipeToUnstashTaskbar();
@@ -217,17 +234,7 @@
break;
case MotionEvent.ACTION_UP:
case MotionEvent.ACTION_CANCEL:
- if (!mIsTransientTaskbar && !mCanceledUnstashHint) {
- mTaskbarActivityContext.startTaskbarUnstashHint(
- /* animateForward = */ false);
- }
- mTaskbarActivityContext.setAutohideSuspendFlag(
- FLAG_AUTOHIDE_SUSPEND_TOUCHING, false);
- if (mTransitionCallback != null) {
- mTransitionCallback.onActionEnd();
- }
- mHasPassedTaskbarNavThreshold = false;
- mIsInBubbleBarArea = false;
+ cleanupAfterMotionEvent();
break;
case MotionEvent.ACTION_BUTTON_RELEASE:
if (isStashedTaskbarHovered) {
@@ -236,9 +243,61 @@
break;
}
}
+ boolean isMovingInBubbleBarArea = mIsInBubbleBarArea && ev.getAction() == ACTION_MOVE;
+ if (!isStashedTaskbarHovered) {
+ // if we're moving in the bubble bar area but we haven't passed the slop yet, don't
+ // propagate to the delegate, until we can determine the direction of the gesture.
+ if (!isMovingInBubbleBarArea || mIsPassedBubbleBarSlop) {
+ mDelegate.onMotionEvent(ev);
+ }
+ }
+ } else if (mIsVerticalGestureOverBubbleBar) {
+ // if we get here then this gesture is a vertical swipe over the bubble bar.
+ // we're also active and there's no need to delegate any additional motion events. the
+ // rest of the gesture will be handled here.
+ switch (ev.getAction()) {
+ case ACTION_MOVE:
+ int pointerIndex = ev.findPointerIndex(mActivePointerId);
+ if (pointerIndex == INVALID_POINTER_ID) {
+ break;
+ }
+ mLastPos.set(ev.getX(pointerIndex), ev.getY(pointerIndex));
+
+ float dY = mLastPos.y - mDownPos.y;
+
+ // bubble bar swipe gesture uses the same threshold as the taskbar.
+ boolean passedTaskbarNavThreshold = dY < 0
+ && Math.abs(dY) >= mTaskbarNavThreshold;
+
+ if (!mHasPassedTaskbarNavThreshold && passedTaskbarNavThreshold) {
+ mHasPassedTaskbarNavThreshold = true;
+ mTaskbarActivityContext.onSwipeToOpenBubblebar();
+ }
+ break;
+ case ACTION_UP:
+ case ACTION_CANCEL:
+ cleanupAfterMotionEvent();
+ break;
+ }
}
}
+ private void cleanupAfterMotionEvent() {
+ if (!mIsTransientTaskbar && !mCanceledUnstashHint) {
+ mTaskbarActivityContext.startTaskbarUnstashHint(
+ /* animateForward = */ false);
+ }
+ mTaskbarActivityContext.setAutohideSuspendFlag(
+ FLAG_AUTOHIDE_SUSPEND_TOUCHING, false);
+ if (mTransitionCallback != null) {
+ mTransitionCallback.onActionEnd();
+ }
+ mHasPassedTaskbarNavThreshold = false;
+ mIsInBubbleBarArea = false;
+ mIsVerticalGestureOverBubbleBar = false;
+ mIsPassedBubbleBarSlop = false;
+ }
+
private boolean isInTaskbarArea(float x) {
float areaFromMiddle = mUnstashArea / 2.0f;
float distFromMiddle = Math.abs(mScreenWidth / 2.0f - x);
@@ -246,13 +305,19 @@
}
private boolean isInBubbleBarArea(float x) {
- if (mTaskbarActivityContext != null && mIsTransientTaskbar) {
- BubbleControllers controllers = mTaskbarActivityContext.getBubbleControllers();
- if (controllers == null) return false;
+ if (mTaskbarActivityContext == null || !mIsTransientTaskbar) {
+ return false;
+ }
+ BubbleControllers controllers = mTaskbarActivityContext.getBubbleControllers();
+ if (controllers == null) {
+ return false;
+ }
+ if (controllers.bubbleStashController.isStashed()) {
+ return controllers.bubbleStashedHandleViewController.containsX((int) x);
+ } else {
Rect bubbleBarBounds = controllers.bubbleBarViewController.getBubbleBarBounds();
return x >= bubbleBarBounds.left && x <= bubbleBarBounds.right;
}
- return false;
}
private void onLongPressDetected(MotionEvent motionEvent) {