diff options
| author | 2023-11-29 21:46:39 +0800 | |
|---|---|---|
| committer | 2023-12-01 20:42:37 +0800 | |
| commit | 120e7c468e3065bf7d4fb4ca8d1772867a046fb8 (patch) | |
| tree | 61dc0a2f750b75aa8ce8c4986cfbcb0522e89997 | |
| parent | bd1371b44cd01ff7a9832a94b408d20de82c5630 (diff) | |
fix(MultiFingerMultiTap): The two finger triple tap is hard work when Magnification is activated
1. ACTION_POINTER_DONW: The two-finger triple tap and two-finger swipe are closely similar gestures when the user doesn't complete the triple tap. To differentiate between these gestures, we implement a delay and utilize the ACTION_UP event to determine whether it's a multi-tap or single-tap gesture.
2. ACTION_MOVE: When the ACTION_MOVE event is triggered before ACTION_PINTER_DONW for second tap, mSecondPointerDownLocation has already been set during the ACTION_POINTER_DOWN of first tap and we stop it transition to the panning state due to a two-finger triple tap (ACTION_UP), so, we need to check the value of mCompletedTapCount for second tap.
NO_IFTTT=add the multi-finger multi-tap feature without syncing to the old state
Bug: 313721606
Test: manual
Test: atest FullScreenMagnificationGestureHandlerTest
Change-Id: I136185e96b621f595d4feb8cc774264161237493
2 files changed, 72 insertions, 15 deletions
diff --git a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java index e3797c98bebe..f55ecb05c55f 100644 --- a/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java +++ b/services/accessibility/java/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandler.java @@ -916,18 +916,27 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH && event.getPointerCount() == 2; mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE); - if (isActivated() && event.getPointerCount() == 2) { - storePointerDownLocation(mSecondPointerDownLocation, event); - mHandler.sendEmptyMessageDelayed(MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE, - ViewConfiguration.getTapTimeout()); - } else if (mIsTwoFingerCountReached) { - // Placing two-finger triple-taps behind isActivated to avoid - // blocking panning scaling state + if (event.getPointerCount() == 2) { if (isMultiFingerMultiTapTriggered(/* targetTapCount= */ 2, event)) { // 3tap and hold afterLongTapTimeoutTransitionToDraggingState(event); } else { - afterMultiTapTimeoutTransitionToDelegatingState(); + if (mDetectTwoFingerTripleTap) { + // If mDetectTwoFingerTripleTap, delay transition to the delegating + // state for mMultiTapMaxDelay to ensure reachability of + // multi finger multi tap + afterMultiTapTimeoutTransitionToDelegatingState(); + } + + if (isActivated()) { + // If activated, delay transition to the panning scaling + // state for tap timeout to ensure reachability of + // multi finger multi tap + storePointerDownLocation(mSecondPointerDownLocation, event); + mHandler.sendEmptyMessageDelayed( + MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE, + ViewConfiguration.getTapTimeout()); + } } } else { transitionToDelegatingStateAndClear(); @@ -953,6 +962,9 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH // (which is a rare combo to be used aside from magnification) if (isMultiTapTriggered(2 /* taps */) && event.getPointerCount() == 1) { transitionToViewportDraggingStateAndClear(event); + } else if (isMultiFingerMultiTapTriggered(/* targetTapCount= */ 2, event) + && event.getPointerCount() == 2) { + transitionToViewportDraggingStateAndClear(event); } else if (isActivated() && event.getPointerCount() == 2) { if (mIsSinglePanningEnabled && overscrollState(event, mFirstPointerDownLocation) @@ -961,11 +973,6 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH } //Primary pointer is swiping, so transit to PanningScalingState transitToPanningScalingStateAndClear(); - } else if (isMultiFingerMultiTapTriggered(/* targetTapCount= */ 2, event) - && event.getPointerCount() == 2) { - // Placing two-finger triple-taps behind isActivated to avoid - // blocking panning scaling state - transitionToViewportDraggingStateAndClear(event); } else if (mIsSinglePanningEnabled && isActivated() && event.getPointerCount() == 1) { @@ -979,8 +986,11 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH } } else if (isActivated() && pointerDownValid(mSecondPointerDownLocation) && distanceClosestPointerToPoint( - mSecondPointerDownLocation, /* move */ event) > mSwipeMinDistance) { - //Second pointer is swiping, so transit to PanningScalingState + mSecondPointerDownLocation, /* move */ event) > mSwipeMinDistance + // If mCompleteTapCount is not zero, it means that it is a multi tap + // gesture. So, we should not transit to the PanningScalingState. + && mCompletedTapCount == 0) { + // Second pointer is swiping, so transit to PanningScalingState transitToPanningScalingStateAndClear(); } } @@ -988,6 +998,7 @@ public class FullScreenMagnificationGestureHandler extends MagnificationGestureH case ACTION_UP: { mHandler.removeMessages(MESSAGE_ON_TRIPLE_TAP_AND_HOLD); + mHandler.removeMessages(MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE); if (!mFullScreenMagnificationController.magnificationRegionContains( mDisplayId, event.getX(), event.getY())) { diff --git a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java index 3b39160643d1..91140276cde0 100644 --- a/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java +++ b/services/tests/servicestests/src/com/android/server/accessibility/magnification/FullScreenMagnificationGestureHandlerTest.java @@ -588,6 +588,38 @@ public class FullScreenMagnificationGestureHandlerTest { } @Test + @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE) + public void testTwoFingerTap_StateIsActivated_shouldInDelegating() { + assumeTrue(mMgh.mIsSinglePanningEnabled); + mMgh.setSinglePanningEnabled(false); + goFromStateIdleTo(STATE_ACTIVATED); + allowEventDelegation(); + + send(downEvent()); + send(pointerEvent(ACTION_POINTER_DOWN, DEFAULT_X * 2, DEFAULT_Y)); + send(upEvent()); + fastForward(ViewConfiguration.getDoubleTapTimeout()); + + assertTrue(mMgh.mCurrentState == mMgh.mDelegatingState); + } + + @Test + @RequiresFlagsEnabled(Flags.FLAG_ENABLE_MAGNIFICATION_MULTIPLE_FINGER_MULTIPLE_TAP_GESTURE) + public void testTwoFingerTap_StateIsIdle_shouldInDelegating() { + assumeTrue(mMgh.mIsSinglePanningEnabled); + mMgh.setSinglePanningEnabled(false); + goFromStateIdleTo(STATE_IDLE); + allowEventDelegation(); + + send(downEvent()); + send(pointerEvent(ACTION_POINTER_DOWN, DEFAULT_X * 2, DEFAULT_Y)); + send(upEvent()); + fastForward(ViewConfiguration.getDoubleTapTimeout()); + + assertTrue(mMgh.mCurrentState == mMgh.mDelegatingState); + } + + @Test public void testMultiTap_outOfDistanceSlop_shouldInIdle() { // All delay motion events should be sent, if multi-tap with out of distance slop. // STATE_IDLE will check if tapCount() < 2. @@ -719,6 +751,20 @@ public class FullScreenMagnificationGestureHandlerTest { } @Test + public void testTwoFingerDown_twoPointerDownAndActivatedState_panningState() { + goFromStateIdleTo(STATE_ACTIVATED); + PointF pointer1 = DEFAULT_POINT; + PointF pointer2 = new PointF(DEFAULT_X * 1.5f, DEFAULT_Y); + + send(downEvent()); + send(pointerEvent(ACTION_POINTER_DOWN, new PointF[] {pointer1, pointer2}, 1)); + fastForward(ViewConfiguration.getTapTimeout()); + assertIn(STATE_PANNING); + + returnToNormalFrom(STATE_PANNING); + } + + @Test public void testActivatedWithTripleTap_invokeShowWindowPromptAction() { goFromStateIdleTo(STATE_ACTIVATED); |