Merge "Fix the multi-fingers gesture conflict with TouchExplorer" into rvc-dev am: 18905eb623 am: 9c1cda1e5e am: 450e5ca964
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/11953898 Change-Id: I5c91dfcd79cd9c6d797b619b775accf98cd5bd5e
This commit is contained in:
@@ -26,6 +26,7 @@ import static android.view.MotionEvent.ACTION_UP;
|
|||||||
|
|
||||||
import static com.android.internal.accessibility.util.AccessibilityStatsLogUtils.logMagnificationTripleTap;
|
import static com.android.internal.accessibility.util.AccessibilityStatsLogUtils.logMagnificationTripleTap;
|
||||||
import static com.android.server.accessibility.gestures.GestureUtils.distance;
|
import static com.android.server.accessibility.gestures.GestureUtils.distance;
|
||||||
|
import static com.android.server.accessibility.gestures.GestureUtils.distanceClosestPointerToPoint;
|
||||||
|
|
||||||
import static java.lang.Math.abs;
|
import static java.lang.Math.abs;
|
||||||
import static java.util.Arrays.asList;
|
import static java.util.Arrays.asList;
|
||||||
@@ -37,6 +38,7 @@ import android.content.BroadcastReceiver;
|
|||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
|
import android.graphics.PointF;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Looper;
|
import android.os.Looper;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
@@ -615,6 +617,7 @@ class FullScreenMagnificationGestureHandler extends MagnificationGestureHandler
|
|||||||
|
|
||||||
private static final int MESSAGE_ON_TRIPLE_TAP_AND_HOLD = 1;
|
private static final int MESSAGE_ON_TRIPLE_TAP_AND_HOLD = 1;
|
||||||
private static final int MESSAGE_TRANSITION_TO_DELEGATING_STATE = 2;
|
private static final int MESSAGE_TRANSITION_TO_DELEGATING_STATE = 2;
|
||||||
|
private static final int MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE = 3;
|
||||||
|
|
||||||
final int mLongTapMinDelay;
|
final int mLongTapMinDelay;
|
||||||
final int mSwipeMinDistance;
|
final int mSwipeMinDistance;
|
||||||
@@ -626,6 +629,7 @@ class FullScreenMagnificationGestureHandler extends MagnificationGestureHandler
|
|||||||
private MotionEvent mPreLastDown;
|
private MotionEvent mPreLastDown;
|
||||||
private MotionEvent mLastUp;
|
private MotionEvent mLastUp;
|
||||||
private MotionEvent mPreLastUp;
|
private MotionEvent mPreLastUp;
|
||||||
|
private PointF mSecondPointerDownLocation = new PointF(Float.NaN, Float.NaN);
|
||||||
|
|
||||||
private long mLastDetectingDownEventTime;
|
private long mLastDetectingDownEventTime;
|
||||||
|
|
||||||
@@ -656,6 +660,10 @@ class FullScreenMagnificationGestureHandler extends MagnificationGestureHandler
|
|||||||
transitionToDelegatingStateAndClear();
|
transitionToDelegatingStateAndClear();
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE: {
|
||||||
|
transitToPanningScalingStateAndClear();
|
||||||
|
}
|
||||||
|
break;
|
||||||
default: {
|
default: {
|
||||||
throw new IllegalArgumentException("Unknown message type: " + type);
|
throw new IllegalArgumentException("Unknown message type: " + type);
|
||||||
}
|
}
|
||||||
@@ -702,14 +710,20 @@ class FullScreenMagnificationGestureHandler extends MagnificationGestureHandler
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case ACTION_POINTER_DOWN: {
|
case ACTION_POINTER_DOWN: {
|
||||||
if (mMagnificationController.isMagnifying(mDisplayId)) {
|
if (mMagnificationController.isMagnifying(mDisplayId)
|
||||||
transitionTo(mPanningScalingState);
|
&& event.getPointerCount() == 2) {
|
||||||
clear();
|
storeSecondPointerDownLocation(event);
|
||||||
|
mHandler.sendEmptyMessageDelayed(MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE,
|
||||||
|
ViewConfiguration.getTapTimeout());
|
||||||
} else {
|
} else {
|
||||||
transitionToDelegatingStateAndClear();
|
transitionToDelegatingStateAndClear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ACTION_POINTER_UP: {
|
||||||
|
transitionToDelegatingStateAndClear();
|
||||||
|
}
|
||||||
|
break;
|
||||||
case ACTION_MOVE: {
|
case ACTION_MOVE: {
|
||||||
if (isFingerDown()
|
if (isFingerDown()
|
||||||
&& distance(mLastDown, /* move */ event) > mSwipeMinDistance) {
|
&& distance(mLastDown, /* move */ event) > mSwipeMinDistance) {
|
||||||
@@ -719,11 +733,19 @@ class FullScreenMagnificationGestureHandler extends MagnificationGestureHandler
|
|||||||
// For convenience, viewport dragging takes precedence
|
// For convenience, viewport dragging takes precedence
|
||||||
// over insta-delegating on 3tap&swipe
|
// over insta-delegating on 3tap&swipe
|
||||||
// (which is a rare combo to be used aside from magnification)
|
// (which is a rare combo to be used aside from magnification)
|
||||||
if (isMultiTapTriggered(2 /* taps */)) {
|
if (isMultiTapTriggered(2 /* taps */) && event.getPointerCount() == 1) {
|
||||||
transitionToViewportDraggingStateAndClear(event);
|
transitionToViewportDraggingStateAndClear(event);
|
||||||
|
} else if (isMagnifying() && event.getPointerCount() == 2) {
|
||||||
|
//Primary pointer is swiping, so transit to PanningScalingState
|
||||||
|
transitToPanningScalingStateAndClear();
|
||||||
} else {
|
} else {
|
||||||
transitionToDelegatingStateAndClear();
|
transitionToDelegatingStateAndClear();
|
||||||
}
|
}
|
||||||
|
} else if (isMagnifying() && secondPointerDownValid()
|
||||||
|
&& distanceClosestPointerToPoint(
|
||||||
|
mSecondPointerDownLocation, /* move */ event) > mSwipeMinDistance) {
|
||||||
|
//Second pointer is swiping, so transit to PanningScalingState
|
||||||
|
transitToPanningScalingStateAndClear();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@@ -755,6 +777,21 @@ class FullScreenMagnificationGestureHandler extends MagnificationGestureHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void storeSecondPointerDownLocation(MotionEvent event) {
|
||||||
|
final int index = event.getActionIndex();
|
||||||
|
mSecondPointerDownLocation.set(event.getX(index), event.getY(index));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean secondPointerDownValid() {
|
||||||
|
return !(Float.isNaN(mSecondPointerDownLocation.x) && Float.isNaN(
|
||||||
|
mSecondPointerDownLocation.y));
|
||||||
|
}
|
||||||
|
|
||||||
|
private void transitToPanningScalingStateAndClear() {
|
||||||
|
transitionTo(mPanningScalingState);
|
||||||
|
clear();
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isMultiTapTriggered(int numTaps) {
|
public boolean isMultiTapTriggered(int numTaps) {
|
||||||
|
|
||||||
// Shortcut acts as the 2 initial taps
|
// Shortcut acts as the 2 initial taps
|
||||||
@@ -822,11 +859,13 @@ class FullScreenMagnificationGestureHandler extends MagnificationGestureHandler
|
|||||||
setShortcutTriggered(false);
|
setShortcutTriggered(false);
|
||||||
removePendingDelayedMessages();
|
removePendingDelayedMessages();
|
||||||
clearDelayedMotionEvents();
|
clearDelayedMotionEvents();
|
||||||
|
mSecondPointerDownLocation.set(Float.NaN, Float.NaN);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void removePendingDelayedMessages() {
|
private void removePendingDelayedMessages() {
|
||||||
mHandler.removeMessages(MESSAGE_ON_TRIPLE_TAP_AND_HOLD);
|
mHandler.removeMessages(MESSAGE_ON_TRIPLE_TAP_AND_HOLD);
|
||||||
mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE);
|
mHandler.removeMessages(MESSAGE_TRANSITION_TO_DELEGATING_STATE);
|
||||||
|
mHandler.removeMessages(MESSAGE_TRANSITION_TO_PANNINGSCALING_STATE);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cacheDelayedMotionEvent(MotionEvent event, MotionEvent rawEvent,
|
private void cacheDelayedMotionEvent(MotionEvent event, MotionEvent rawEvent,
|
||||||
@@ -890,6 +929,7 @@ class FullScreenMagnificationGestureHandler extends MagnificationGestureHandler
|
|||||||
transitionTo(mDelegatingState);
|
transitionTo(mDelegatingState);
|
||||||
sendDelayedMotionEvents();
|
sendDelayedMotionEvents();
|
||||||
removePendingDelayedMessages();
|
removePendingDelayedMessages();
|
||||||
|
mSecondPointerDownLocation.set(Float.NaN, Float.NaN);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onTripleTap(MotionEvent up) {
|
private void onTripleTap(MotionEvent up) {
|
||||||
@@ -907,6 +947,10 @@ class FullScreenMagnificationGestureHandler extends MagnificationGestureHandler
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private boolean isMagnifying() {
|
||||||
|
return mMagnificationController.isMagnifying(mDisplayId);
|
||||||
|
}
|
||||||
|
|
||||||
void transitionToViewportDraggingStateAndClear(MotionEvent down) {
|
void transitionToViewportDraggingStateAndClear(MotionEvent down) {
|
||||||
|
|
||||||
if (DEBUG_DETECTING) Slog.i(LOG_TAG, "onTripleTapAndHold()");
|
if (DEBUG_DETECTING) Slog.i(LOG_TAG, "onTripleTapAndHold()");
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
package com.android.server.accessibility.gestures;
|
package com.android.server.accessibility.gestures;
|
||||||
|
|
||||||
|
import android.graphics.PointF;
|
||||||
import android.util.MathUtils;
|
import android.util.MathUtils;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
|
||||||
@@ -38,6 +39,27 @@ public final class GestureUtils {
|
|||||||
return MathUtils.dist(first.getX(), first.getY(), second.getX(), second.getY());
|
return MathUtils.dist(first.getX(), first.getY(), second.getX(), second.getY());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the minimum distance between {@code pointerDown} and each pointer of
|
||||||
|
* {@link MotionEvent}.
|
||||||
|
*
|
||||||
|
* @param pointerDown The action pointer location of the {@link MotionEvent} with
|
||||||
|
* {@link MotionEvent#ACTION_DOWN} or {@link MotionEvent#ACTION_POINTER_DOWN}
|
||||||
|
* @param moveEvent The {@link MotionEvent} with {@link MotionEvent#ACTION_MOVE}
|
||||||
|
* @return the movement of the pointer.
|
||||||
|
*/
|
||||||
|
public static double distanceClosestPointerToPoint(PointF pointerDown, MotionEvent moveEvent) {
|
||||||
|
float movement = Float.MAX_VALUE;
|
||||||
|
for (int i = 0; i < moveEvent.getPointerCount(); i++) {
|
||||||
|
final float moveDelta = MathUtils.dist(pointerDown.x, pointerDown.y, moveEvent.getX(i),
|
||||||
|
moveEvent.getY(i));
|
||||||
|
if (movement > moveDelta) {
|
||||||
|
movement = moveDelta;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return movement;
|
||||||
|
}
|
||||||
|
|
||||||
public static boolean isTimedOut(MotionEvent firstUp, MotionEvent secondUp, int timeout) {
|
public static boolean isTimedOut(MotionEvent firstUp, MotionEvent secondUp, int timeout) {
|
||||||
final long deltaTime = secondUp.getEventTime() - firstUp.getEventTime();
|
final long deltaTime = secondUp.getEventTime() - firstUp.getEventTime();
|
||||||
return (deltaTime >= timeout);
|
return (deltaTime >= timeout);
|
||||||
|
|||||||
@@ -20,6 +20,7 @@ import static android.view.MotionEvent.ACTION_DOWN;
|
|||||||
import static android.view.MotionEvent.ACTION_MOVE;
|
import static android.view.MotionEvent.ACTION_MOVE;
|
||||||
import static android.view.MotionEvent.ACTION_POINTER_DOWN;
|
import static android.view.MotionEvent.ACTION_POINTER_DOWN;
|
||||||
import static android.view.MotionEvent.ACTION_POINTER_UP;
|
import static android.view.MotionEvent.ACTION_POINTER_UP;
|
||||||
|
import static android.view.MotionEvent.ACTION_UP;
|
||||||
|
|
||||||
import static com.android.server.testutils.TestUtils.strictMock;
|
import static com.android.server.testutils.TestUtils.strictMock;
|
||||||
|
|
||||||
@@ -38,11 +39,13 @@ import static org.mockito.Mockito.when;
|
|||||||
import android.animation.ValueAnimator;
|
import android.animation.ValueAnimator;
|
||||||
import android.annotation.NonNull;
|
import android.annotation.NonNull;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
import android.graphics.PointF;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
import android.os.Message;
|
import android.os.Message;
|
||||||
import android.util.DebugUtils;
|
import android.util.DebugUtils;
|
||||||
import android.view.InputDevice;
|
import android.view.InputDevice;
|
||||||
import android.view.MotionEvent;
|
import android.view.MotionEvent;
|
||||||
|
import android.view.ViewConfiguration;
|
||||||
|
|
||||||
import androidx.test.InstrumentationRegistry;
|
import androidx.test.InstrumentationRegistry;
|
||||||
import androidx.test.runner.AndroidJUnit4;
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
@@ -56,6 +59,9 @@ import org.junit.Before;
|
|||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
import java.util.function.IntConsumer;
|
import java.util.function.IntConsumer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -106,6 +112,7 @@ public class FullScreenMagnificationGestureHandlerTest {
|
|||||||
// Co-prime x and y, to potentially catch x-y-swapped errors
|
// Co-prime x and y, to potentially catch x-y-swapped errors
|
||||||
public static final float DEFAULT_X = 301;
|
public static final float DEFAULT_X = 301;
|
||||||
public static final float DEFAULT_Y = 299;
|
public static final float DEFAULT_Y = 299;
|
||||||
|
public static final PointF DEFAULT_POINT = new PointF(DEFAULT_X, DEFAULT_Y);
|
||||||
|
|
||||||
private static final int DISPLAY_0 = 0;
|
private static final int DISPLAY_0 = 0;
|
||||||
|
|
||||||
@@ -327,6 +334,107 @@ public class FullScreenMagnificationGestureHandlerTest {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testTwoFingersOneTap_zoomedState_dispatchMotionEvents() {
|
||||||
|
goFromStateIdleTo(STATE_ZOOMED);
|
||||||
|
final EventCaptor eventCaptor = new EventCaptor();
|
||||||
|
mMgh.setNext(eventCaptor);
|
||||||
|
|
||||||
|
send(downEvent());
|
||||||
|
send(pointerEvent(ACTION_POINTER_DOWN, DEFAULT_X * 2, DEFAULT_Y));
|
||||||
|
send(pointerEvent(ACTION_POINTER_UP, DEFAULT_X * 2, DEFAULT_Y));
|
||||||
|
send(upEvent());
|
||||||
|
|
||||||
|
assertIn(STATE_ZOOMED);
|
||||||
|
final List<Integer> expectedActions = new ArrayList();
|
||||||
|
expectedActions.add(Integer.valueOf(ACTION_DOWN));
|
||||||
|
expectedActions.add(Integer.valueOf(ACTION_POINTER_DOWN));
|
||||||
|
expectedActions.add(Integer.valueOf(ACTION_POINTER_UP));
|
||||||
|
expectedActions.add(Integer.valueOf(ACTION_UP));
|
||||||
|
assertActionsInOrder(eventCaptor.mEvents, expectedActions);
|
||||||
|
|
||||||
|
returnToNormalFrom(STATE_ZOOMED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testThreeFingersOneTap_zoomedState_dispatchMotionEvents() {
|
||||||
|
goFromStateIdleTo(STATE_ZOOMED);
|
||||||
|
final EventCaptor eventCaptor = new EventCaptor();
|
||||||
|
mMgh.setNext(eventCaptor);
|
||||||
|
PointF pointer1 = DEFAULT_POINT;
|
||||||
|
PointF pointer2 = new PointF(DEFAULT_X * 1.5f, DEFAULT_Y);
|
||||||
|
PointF pointer3 = new PointF(DEFAULT_X * 2, DEFAULT_Y);
|
||||||
|
|
||||||
|
send(downEvent());
|
||||||
|
send(pointerEvent(ACTION_POINTER_DOWN, new PointF[] {pointer1, pointer2}));
|
||||||
|
send(pointerEvent(ACTION_POINTER_DOWN, new PointF[] {pointer1, pointer2, pointer3}));
|
||||||
|
send(pointerEvent(ACTION_POINTER_UP, new PointF[] {pointer1, pointer2, pointer3}));
|
||||||
|
send(pointerEvent(ACTION_POINTER_UP, new PointF[] {pointer1, pointer2, pointer3}));
|
||||||
|
send(upEvent());
|
||||||
|
|
||||||
|
assertIn(STATE_ZOOMED);
|
||||||
|
final List<Integer> expectedActions = new ArrayList();
|
||||||
|
expectedActions.add(Integer.valueOf(ACTION_DOWN));
|
||||||
|
expectedActions.add(Integer.valueOf(ACTION_POINTER_DOWN));
|
||||||
|
expectedActions.add(Integer.valueOf(ACTION_POINTER_DOWN));
|
||||||
|
expectedActions.add(Integer.valueOf(ACTION_POINTER_UP));
|
||||||
|
expectedActions.add(Integer.valueOf(ACTION_POINTER_UP));
|
||||||
|
expectedActions.add(Integer.valueOf(ACTION_UP));
|
||||||
|
assertActionsInOrder(eventCaptor.mEvents, expectedActions);
|
||||||
|
|
||||||
|
returnToNormalFrom(STATE_ZOOMED);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testFirstFingerSwipe_TwoPinterDownAndZoomedState_panningState() {
|
||||||
|
goFromStateIdleTo(STATE_ZOOMED);
|
||||||
|
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}));
|
||||||
|
//The minimum movement to transit to panningState.
|
||||||
|
final float sWipeMinDistance = ViewConfiguration.get(mContext).getScaledTouchSlop();
|
||||||
|
pointer1.offset(sWipeMinDistance + 1, 0);
|
||||||
|
send(pointerEvent(ACTION_MOVE, new PointF[] {pointer1, pointer2}));
|
||||||
|
assertIn(STATE_PANNING);
|
||||||
|
|
||||||
|
assertIn(STATE_PANNING);
|
||||||
|
returnToNormalFrom(STATE_PANNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testSecondFingerSwipe_TwoPinterDownAndZoomedState_panningState() {
|
||||||
|
goFromStateIdleTo(STATE_ZOOMED);
|
||||||
|
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}));
|
||||||
|
//The minimum movement to transit to panningState.
|
||||||
|
final float sWipeMinDistance = ViewConfiguration.get(mContext).getScaledTouchSlop();
|
||||||
|
pointer2.offset(sWipeMinDistance + 1, 0);
|
||||||
|
send(pointerEvent(ACTION_MOVE, new PointF[] {pointer1, pointer2}));
|
||||||
|
assertIn(STATE_PANNING);
|
||||||
|
|
||||||
|
assertIn(STATE_PANNING);
|
||||||
|
returnToNormalFrom(STATE_PANNING);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void assertActionsInOrder(List<MotionEvent> actualEvents,
|
||||||
|
List<Integer> expectedActions) {
|
||||||
|
assertTrue(actualEvents.size() == expectedActions.size());
|
||||||
|
final int size = actualEvents.size();
|
||||||
|
for (int i = 0; i < size; i++) {
|
||||||
|
final int expectedAction = expectedActions.get(i);
|
||||||
|
final int actualAction = actualEvents.get(i).getActionMasked();
|
||||||
|
assertTrue(String.format(
|
||||||
|
"%dth action %s is not matched, actual events : %s, ", i,
|
||||||
|
MotionEvent.actionToString(expectedAction), actualEvents),
|
||||||
|
actualAction == expectedAction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void assertZoomsImmediatelyOnSwipeFrom(int state) {
|
private void assertZoomsImmediatelyOnSwipeFrom(int state) {
|
||||||
goFromStateIdleTo(state);
|
goFromStateIdleTo(state);
|
||||||
swipeAndHold();
|
swipeAndHold();
|
||||||
@@ -467,6 +575,7 @@ public class FullScreenMagnificationGestureHandlerTest {
|
|||||||
goFromStateIdleTo(STATE_ZOOMED);
|
goFromStateIdleTo(STATE_ZOOMED);
|
||||||
send(downEvent());
|
send(downEvent());
|
||||||
send(pointerEvent(ACTION_POINTER_DOWN, DEFAULT_X * 2, DEFAULT_Y));
|
send(pointerEvent(ACTION_POINTER_DOWN, DEFAULT_X * 2, DEFAULT_Y));
|
||||||
|
fastForward(ViewConfiguration.getTapTimeout());
|
||||||
} break;
|
} break;
|
||||||
case STATE_SCALING_AND_PANNING: {
|
case STATE_SCALING_AND_PANNING: {
|
||||||
goFromStateIdleTo(STATE_PANNING);
|
goFromStateIdleTo(STATE_PANNING);
|
||||||
@@ -619,40 +728,67 @@ public class FullScreenMagnificationGestureHandlerTest {
|
|||||||
MotionEvent.ACTION_UP, x, y, 0));
|
MotionEvent.ACTION_UP, x, y, 0));
|
||||||
}
|
}
|
||||||
|
|
||||||
private MotionEvent pointerEvent(int action, float x, float y) {
|
|
||||||
MotionEvent.PointerProperties defPointerProperties = new MotionEvent.PointerProperties();
|
|
||||||
defPointerProperties.id = 0;
|
|
||||||
defPointerProperties.toolType = MotionEvent.TOOL_TYPE_FINGER;
|
|
||||||
MotionEvent.PointerProperties pointerProperties = new MotionEvent.PointerProperties();
|
|
||||||
pointerProperties.id = 1;
|
|
||||||
pointerProperties.toolType = MotionEvent.TOOL_TYPE_FINGER;
|
|
||||||
|
|
||||||
MotionEvent.PointerCoords defPointerCoords = new MotionEvent.PointerCoords();
|
private MotionEvent pointerEvent(int action, float x, float y) {
|
||||||
defPointerCoords.x = DEFAULT_X;
|
return pointerEvent(action, new PointF[] {DEFAULT_POINT, new PointF(x, y)});
|
||||||
defPointerCoords.y = DEFAULT_Y;
|
}
|
||||||
MotionEvent.PointerCoords pointerCoords = new MotionEvent.PointerCoords();
|
|
||||||
pointerCoords.x = x;
|
private MotionEvent pointerEvent(int action, PointF[] pointersPosition) {
|
||||||
pointerCoords.y = y;
|
final MotionEvent.PointerProperties[] PointerPropertiesArray =
|
||||||
|
new MotionEvent.PointerProperties[pointersPosition.length];
|
||||||
|
for (int i = 0; i < pointersPosition.length; i++) {
|
||||||
|
MotionEvent.PointerProperties pointerProperties = new MotionEvent.PointerProperties();
|
||||||
|
pointerProperties.id = i;
|
||||||
|
pointerProperties.toolType = MotionEvent.TOOL_TYPE_FINGER;
|
||||||
|
PointerPropertiesArray[i] = pointerProperties;
|
||||||
|
}
|
||||||
|
|
||||||
|
final MotionEvent.PointerCoords[] pointerCoordsArray =
|
||||||
|
new MotionEvent.PointerCoords[pointersPosition.length];
|
||||||
|
for (int i = 0; i < pointersPosition.length; i++) {
|
||||||
|
MotionEvent.PointerCoords pointerCoords = new MotionEvent.PointerCoords();
|
||||||
|
pointerCoords.x = pointersPosition[i].x;
|
||||||
|
pointerCoords.y = pointersPosition[i].y;
|
||||||
|
pointerCoordsArray[i] = pointerCoords;
|
||||||
|
}
|
||||||
|
|
||||||
return MotionEvent.obtain(
|
return MotionEvent.obtain(
|
||||||
/* downTime */ mClock.now(),
|
/* downTime */ mClock.now(),
|
||||||
/* eventTime */ mClock.now(),
|
/* eventTime */ mClock.now(),
|
||||||
/* action */ action,
|
/* action */ action,
|
||||||
/* pointerCount */ 2,
|
/* pointerCount */ pointersPosition.length,
|
||||||
/* pointerProperties */ new MotionEvent.PointerProperties[] {
|
/* pointerProperties */ PointerPropertiesArray,
|
||||||
defPointerProperties, pointerProperties},
|
/* pointerCoords */ pointerCoordsArray,
|
||||||
/* pointerCoords */ new MotionEvent.PointerCoords[] { defPointerCoords, pointerCoords },
|
/* metaState */ 0,
|
||||||
/* metaState */ 0,
|
/* buttonState */ 0,
|
||||||
/* buttonState */ 0,
|
/* xPrecision */ 1.0f,
|
||||||
/* xPrecision */ 1.0f,
|
/* yPrecision */ 1.0f,
|
||||||
/* yPrecision */ 1.0f,
|
/* deviceId */ 0,
|
||||||
/* deviceId */ 0,
|
/* edgeFlags */ 0,
|
||||||
/* edgeFlags */ 0,
|
/* source */ InputDevice.SOURCE_TOUCHSCREEN,
|
||||||
/* source */ InputDevice.SOURCE_TOUCHSCREEN,
|
/* flags */ 0);
|
||||||
/* flags */ 0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private String stateDump() {
|
private String stateDump() {
|
||||||
return "\nCurrent state dump:\n" + mMgh + "\n" + mHandler.getPendingMessages();
|
return "\nCurrent state dump:\n" + mMgh + "\n" + mHandler.getPendingMessages();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private class EventCaptor implements EventStreamTransformation {
|
||||||
|
List<MotionEvent> mEvents = new ArrayList<>();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onMotionEvent(MotionEvent event, MotionEvent rawEvent, int policyFlags) {
|
||||||
|
mEvents.add(event.copy());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setNext(EventStreamTransformation next) {
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EventStreamTransformation getNext() {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user