Merge "Run HOVER_EXIT event only if there's no BUTTON_PRESS event after." into rvc-dev
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index b6e4e16..d7cc11b 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -242,7 +242,8 @@
this::updateMovementBounds, sysUiState);
mTouchState = new PipTouchState(ViewConfiguration.get(context), mHandler,
() -> mMenuController.showMenuWithDelay(MENU_STATE_FULL, mMotionHelper.getBounds(),
- true /* allowMenuTimeout */, willResizeMenu(), shouldShowResizeHandle()));
+ true /* allowMenuTimeout */, willResizeMenu(), shouldShowResizeHandle()),
+ menuController::hideMenu);
Resources res = context.getResources();
mEnableDismissDragToEdge = res.getBoolean(R.bool.config_pipEnableDismissDragToEdge);
@@ -708,6 +709,7 @@
// on and changing MotionEvents into HoverEvents.
// Let's not enable menu show/hide for a11y services.
if (!mAccessibilityManager.isTouchExplorationEnabled()) {
+ mTouchState.removeHoverExitTimeoutCallback();
mMenuController.showMenu(MENU_STATE_FULL, mMotionHelper.getBounds(),
false /* allowMenuTimeout */, false /* willResizeMenu */,
shouldShowResizeHandle());
@@ -725,7 +727,7 @@
// Let's not enable menu show/hide for a11y services.
if (!mAccessibilityManager.isTouchExplorationEnabled()) {
mHideMenuAfterShown = true;
- mMenuController.hideMenu();
+ mTouchState.scheduleHoverExitTimeoutCallback();
}
if (!shouldDeliverToMenu && mSendingHoverAccessibilityEvents) {
sendAccessibilityHoverEvent(AccessibilityEvent.TYPE_VIEW_HOVER_EXIT);
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
index 132c04d..ecd1128a 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchState.java
@@ -36,10 +36,12 @@
@VisibleForTesting
static final long DOUBLE_TAP_TIMEOUT = 200;
+ static final long HOVER_EXIT_TIMEOUT = 50;
private final Handler mHandler;
private final ViewConfiguration mViewConfig;
private final Runnable mDoubleTapTimeoutCallback;
+ private final Runnable mHoverExitTimeoutCallback;
private VelocityTracker mVelocityTracker;
private long mDownTouchTime = 0;
@@ -64,10 +66,11 @@
private int mActivePointerId;
public PipTouchState(ViewConfiguration viewConfig, Handler handler,
- Runnable doubleTapTimeoutCallback) {
+ Runnable doubleTapTimeoutCallback, Runnable hoverExitTimeoutCallback) {
mViewConfig = viewConfig;
mHandler = handler;
mDoubleTapTimeoutCallback = doubleTapTimeoutCallback;
+ mHoverExitTimeoutCallback = hoverExitTimeoutCallback;
}
/**
@@ -197,6 +200,10 @@
recycleVelocityTracker();
break;
}
+ case MotionEvent.ACTION_BUTTON_PRESS: {
+ removeHoverExitTimeoutCallback();
+ break;
+ }
}
}
@@ -326,6 +333,15 @@
mHandler.removeCallbacks(mDoubleTapTimeoutCallback);
}
+ void scheduleHoverExitTimeoutCallback() {
+ mHandler.removeCallbacks(mHoverExitTimeoutCallback);
+ mHandler.postDelayed(mHoverExitTimeoutCallback, HOVER_EXIT_TIMEOUT);
+ }
+
+ void removeHoverExitTimeoutCallback() {
+ mHandler.removeCallbacks(mHoverExitTimeoutCallback);
+ }
+
void addMovementToVelocityTracker(MotionEvent event) {
if (mVelocityTracker == null) {
return;
diff --git a/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTouchStateTest.java b/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTouchStateTest.java
index 3155e57..17b2e32 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTouchStateTest.java
+++ b/packages/SystemUI/tests/src/com/android/systemui/pip/phone/PipTouchStateTest.java
@@ -16,6 +16,7 @@
package com.android.systemui.pip.phone;
+import static android.view.MotionEvent.ACTION_BUTTON_PRESS;
import static android.view.MotionEvent.ACTION_DOWN;
import static android.view.MotionEvent.ACTION_MOVE;
import static android.view.MotionEvent.ACTION_UP;
@@ -49,13 +50,17 @@
private PipTouchState mTouchState;
private CountDownLatch mDoubleTapCallbackTriggeredLatch;
+ private CountDownLatch mHoverExitCallbackTriggeredLatch;
@Before
public void setUp() throws Exception {
mDoubleTapCallbackTriggeredLatch = new CountDownLatch(1);
+ mHoverExitCallbackTriggeredLatch = new CountDownLatch(1);
mTouchState = new PipTouchState(ViewConfiguration.get(getContext()),
Handler.createAsync(Looper.myLooper()), () -> {
mDoubleTapCallbackTriggeredLatch.countDown();
+ }, () -> {
+ mHoverExitCallbackTriggeredLatch.countDown();
});
assertFalse(mTouchState.isDoubleTap());
assertFalse(mTouchState.isWaitingForDoubleTap());
@@ -120,6 +125,35 @@
assertTrue(mTouchState.getDoubleTapTimeoutCallbackDelay() == -1);
}
+ @Test
+ public void testHoverExitTimeout_timeoutCallbackCalled() throws Exception {
+ mTouchState.scheduleHoverExitTimeoutCallback();
+
+ // TODO: Remove this sleep. Its only being added because it speeds up this test a bit.
+ Thread.sleep(50);
+ TestableLooper.get(this).processAllMessages();
+ assertTrue(mHoverExitCallbackTriggeredLatch.getCount() == 0);
+ }
+
+ @Test
+ public void testHoverExitTimeout_timeoutCallbackNotCalled() throws Exception {
+ mTouchState.scheduleHoverExitTimeoutCallback();
+ TestableLooper.get(this).processAllMessages();
+ assertTrue(mHoverExitCallbackTriggeredLatch.getCount() == 1);
+ }
+
+ @Test
+ public void testHoverExitTimeout_timeoutCallbackNotCalled_ifButtonPress() throws Exception {
+ mTouchState.scheduleHoverExitTimeoutCallback();
+ mTouchState.onTouchEvent(createMotionEvent(ACTION_BUTTON_PRESS, SystemClock.uptimeMillis(),
+ 0, 0));
+
+ // TODO: Remove this sleep. Its only being added because it speeds up this test a bit.
+ Thread.sleep(50);
+ TestableLooper.get(this).processAllMessages();
+ assertTrue(mHoverExitCallbackTriggeredLatch.getCount() == 1);
+ }
+
private MotionEvent createMotionEvent(int action, long eventTime, float x, float y) {
return MotionEvent.obtain(0, eventTime, action, x, y, 0);
}