am d367b70c: Merge "Accessibility HOVER_ENTER / EXIT without enclosing EXPLORATION_GESTURE_START / END" into jb-mr1-dev

* commit 'd367b70c4ad5d8e6cdbcc0d6d429428413cd39b3':
  Accessibility HOVER_ENTER / EXIT without enclosing EXPLORATION_GESTURE_START / END
This commit is contained in:
Svetoslav Ganov
2012-10-04 12:32:38 -07:00
committed by Android Git Automerger

View File

@@ -102,10 +102,6 @@ class TouchExplorer implements EventStreamTransformation {
// The timeout after which we are no longer trying to detect a gesture.
private static final int EXIT_GESTURE_DETECTION_TIMEOUT = 2000;
// The timeout to send interaction end events in case we did not
// receive the expected hover exit event due to a misbehaving app.
private static final int SEND_INTERACTION_END_EVENTS_TIMEOUT = 200;
// Temporary array for storing pointer IDs.
private final int[] mTempPointerIds = new int[MAX_POINTER_COUNT];
@@ -139,8 +135,11 @@ class TouchExplorer implements EventStreamTransformation {
// Command for delayed sending of a hover exit event.
private final SendHoverDelayed mSendHoverExitDelayed;
// Command for delayed sending of interaction ending events.
private final SendInteractionEndEventsDelayed mSendInteractionEndEventsDelayed;
// Command for delayed sending of touch exploration end events.
private final SendAccessibilityEventDelayed mSendTouchExplorationEndDelayed;
// Command for delayed sending of touch interaction end events.
private final SendAccessibilityEventDelayed mSendTouchInteractionEndDelayed;
// Command for delayed sending of a long press.
private final PerformLongPressDelayed mPerformLongPressDelayed;
@@ -209,11 +208,8 @@ class TouchExplorer implements EventStreamTransformation {
// The id of the last touch explored window.
private int mLastTouchedWindowId;
// Whether touch exploration gesture has ended.
private boolean mTouchExplorationGestureEnded;
// Whether touch interaction has ended.
private boolean mTouchInteractionEnded;
// Whether touch exploration is in progress.
private boolean mTouchExplorationInProgress;
/**
* Creates a new instance.
@@ -240,7 +236,12 @@ class TouchExplorer implements EventStreamTransformation {
mGestureLibrary.load();
mSendHoverEnterDelayed = new SendHoverDelayed(MotionEvent.ACTION_HOVER_ENTER, true);
mSendHoverExitDelayed = new SendHoverDelayed(MotionEvent.ACTION_HOVER_EXIT, false);
mSendInteractionEndEventsDelayed = new SendInteractionEndEventsDelayed();
mSendTouchExplorationEndDelayed = new SendAccessibilityEventDelayed(
AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END,
mDetermineUserIntentTimeout);
mSendTouchInteractionEndDelayed = new SendAccessibilityEventDelayed(
AccessibilityEvent.TYPE_TOUCH_INTERACTION_END,
mDetermineUserIntentTimeout);
mDoubleTapDetector = new DoubleTapDetector();
final float density = context.getResources().getDisplayMetrics().density;
mScaledMinPointerDistanceToUseMiddleLocation =
@@ -265,7 +266,7 @@ class TouchExplorer implements EventStreamTransformation {
switch (mCurrentState) {
case STATE_TOUCH_EXPLORING: {
// If a touch exploration gesture is in progress send events for its end.
sendExitEventsIfNeeded(policyFlags);
sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
} break;
case STATE_DRAGGING: {
mDraggingPointerId = INVALID_POINTER_ID;
@@ -286,7 +287,8 @@ class TouchExplorer implements EventStreamTransformation {
mSendHoverExitDelayed.remove();
mPerformLongPressDelayed.remove();
mExitGestureDetectionModeDelayed.remove();
mSendInteractionEndEventsDelayed.remove();
mSendTouchExplorationEndDelayed.remove();
mSendTouchInteractionEndDelayed.remove();
// Reset the pointer trackers.
mReceivedPointerTracker.clear();
mInjectedPointerTracker.clear();
@@ -301,6 +303,7 @@ class TouchExplorer implements EventStreamTransformation {
if (mNext != null) {
mNext.clear();
}
mTouchExplorationInProgress = false;
}
@Override
@@ -341,19 +344,17 @@ class TouchExplorer implements EventStreamTransformation {
// The event for gesture end should be strictly after the
// last hover exit event.
if (mTouchExplorationGestureEnded
if (mSendTouchExplorationEndDelayed.isPending()
&& eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
mSendInteractionEndEventsDelayed.remove();
mTouchExplorationGestureEnded = false;
mSendTouchExplorationEndDelayed.remove();
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END);
}
// The event for touch interaction end should be strictly after the
// last hover exit and the touch exploration gesture end events.
if (mTouchInteractionEnded
if (mSendTouchInteractionEndDelayed.isPending()
&& eventType == AccessibilityEvent.TYPE_VIEW_HOVER_EXIT) {
mSendInteractionEndEventsDelayed.remove();
mTouchInteractionEnded = false;
mSendTouchInteractionEndDelayed.remove();
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
}
@@ -396,15 +397,6 @@ class TouchExplorer implements EventStreamTransformation {
switch (event.getActionMasked()) {
case MotionEvent.ACTION_DOWN:
// The delayed enter not delivered implies that we have delivered
// TYPE_TOUCH_INTERACTION_START and not TYPE_TOUCH_INTERACTION_END,
// therefore we need to deliver the interaction end event here.
if (mSendHoverEnterDelayed.isPending()) {
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
}
// Announce the start of a new touch interaction.
sendAccessibilityEvent(
AccessibilityEvent.TYPE_TOUCH_INTERACTION_START);
// Pre-feed the motion events to the gesture detector since we
// have a distance slop before getting into gesture detection
// mode and not using the points within this slop significantly
@@ -426,8 +418,20 @@ class TouchExplorer implements EventStreamTransformation {
mSendHoverExitDelayed.remove();
}
if (mSendInteractionEndEventsDelayed.isPending()) {
mSendInteractionEndEventsDelayed.forceSendAndRemove();
if (mSendTouchExplorationEndDelayed.isPending()) {
mSendTouchExplorationEndDelayed.forceSendAndRemove();
}
if (mSendTouchInteractionEndDelayed.isPending()) {
mSendTouchInteractionEndDelayed.forceSendAndRemove();
}
// Every pointer that goes down is active until it moves or
// another one goes down. Hence, having more than one pointer
// down we have already send the interaction start event.
if (event.getPointerCount() == 1) {
sendAccessibilityEvent(
AccessibilityEvent.TYPE_TOUCH_INTERACTION_START);
}
mPerformLongPressDelayed.remove();
@@ -443,11 +447,13 @@ class TouchExplorer implements EventStreamTransformation {
mPerformLongPressDelayed.post(event, policyFlags);
break;
}
// Deliver hover enter with a delay to have a chance
// to detect what the user is trying to do.
final int pointerId = receivedTracker.getPrimaryActivePointerId();
final int pointerIdBits = (1 << pointerId);
mSendHoverEnterDelayed.post(event, true, pointerIdBits, policyFlags);
if (!mTouchExplorationInProgress) {
// Deliver hover enter with a delay to have a chance
// to detect what the user is trying to do.
final int pointerId = receivedTracker.getPrimaryActivePointerId();
final int pointerIdBits = (1 << pointerId);
mSendHoverEnterDelayed.post(event, true, pointerIdBits, policyFlags);
}
} break;
default: {
/* do nothing - let the code for ACTION_MOVE decide what to do */
@@ -512,12 +518,27 @@ class TouchExplorer implements EventStreamTransformation {
break;
}
} else {
// Cancel the long press if pending and the user
// moved more than the slop.
if (mPerformLongPressDelayed.isPending()) {
final float deltaX =
receivedTracker.getReceivedPointerDownX(pointerId)
- rawEvent.getX(pointerIndex);
final float deltaY =
receivedTracker.getReceivedPointerDownY(pointerId)
- rawEvent.getY(pointerIndex);
final double moveDelta = Math.hypot(deltaX, deltaY);
// The user has moved enough for us to decide.
if (moveDelta > mTouchSlop) {
mPerformLongPressDelayed.remove();
}
}
// The user is wither double tapping or performing long
// press so do not send move events yet.
if (mDoubleTapDetector.firstTapDetected()) {
break;
}
sendEnterEventsIfNeeded(policyFlags);
sendTouchExplorationGestureStartAndHoverEnterIfNeeded(policyFlags);
sendMotionEvent(event, MotionEvent.ACTION_HOVER_MOVE, pointerIdBits,
policyFlags);
}
@@ -548,7 +569,7 @@ class TouchExplorer implements EventStreamTransformation {
}
// We are sending events so send exit and gesture
// end since we transition to another state.
sendExitEventsIfNeeded(policyFlags);
sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
}
// We know that a new state transition is to happen and the
@@ -583,7 +604,7 @@ class TouchExplorer implements EventStreamTransformation {
mPerformLongPressDelayed.remove();
// We are sending events so send exit and gesture
// end since we transition to another state.
sendExitEventsIfNeeded(policyFlags);
sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
}
// More than two pointers are delegated to the view hierarchy.
@@ -612,11 +633,14 @@ class TouchExplorer implements EventStreamTransformation {
// If we have not delivered the enter schedule exit.
if (mSendHoverEnterDelayed.isPending()) {
mSendHoverEnterDelayed.mTouchExplorationInProgress = false;
mSendHoverExitDelayed.post(event, false, pointerIdBits, policyFlags);
} else {
// The user is touch exploring so we send events for end.
sendExitEventsIfNeeded(policyFlags);
sendHoverExitAndTouchExplorationGestureEndIfNeeded(policyFlags);
}
if (!mSendTouchInteractionEndDelayed.isPending()) {
mSendTouchInteractionEndDelayed.post();
}
} break;
}
@@ -846,6 +870,14 @@ class TouchExplorer implements EventStreamTransformation {
if (accessibilityManager.isEnabled()) {
AccessibilityEvent event = AccessibilityEvent.obtain(type);
accessibilityManager.sendAccessibilityEvent(event);
switch (type) {
case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START: {
mTouchExplorationInProgress = true;
} break;
case AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END: {
mTouchExplorationInProgress = false;
} break;
}
}
}
@@ -893,14 +925,12 @@ class TouchExplorer implements EventStreamTransformation {
*
* @param policyFlags The policy flags associated with the event.
*/
private void sendExitEventsIfNeeded(int policyFlags) {
private void sendHoverExitAndTouchExplorationGestureEndIfNeeded(int policyFlags) {
MotionEvent event = mInjectedPointerTracker.getLastInjectedHoverEvent();
if (event != null && event.getActionMasked() != MotionEvent.ACTION_HOVER_EXIT) {
final int pointerIdBits = event.getPointerIdBits();
mTouchExplorationGestureEnded = true;
mTouchInteractionEnded = true;
if (!mSendInteractionEndEventsDelayed.isPending()) {
mSendInteractionEndEventsDelayed.post();
if (!mSendTouchExplorationEndDelayed.isPending()) {
mSendTouchExplorationEndDelayed.post();
}
sendMotionEvent(event, MotionEvent.ACTION_HOVER_EXIT, pointerIdBits, policyFlags);
}
@@ -912,10 +942,11 @@ class TouchExplorer implements EventStreamTransformation {
*
* @param policyFlags The policy flags associated with the event.
*/
private void sendEnterEventsIfNeeded(int policyFlags) {
private void sendTouchExplorationGestureStartAndHoverEnterIfNeeded(int policyFlags) {
MotionEvent event = mInjectedPointerTracker.getLastInjectedHoverEvent();
if (event != null && event.getActionMasked() == MotionEvent.ACTION_HOVER_EXIT) {
final int pointerIdBits = event.getPointerIdBits();
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
sendMotionEvent(event, MotionEvent.ACTION_HOVER_ENTER, pointerIdBits, policyFlags);
}
}
@@ -1181,8 +1212,12 @@ class TouchExplorer implements EventStreamTransformation {
mSendHoverExitDelayed.remove();
mPerformLongPressDelayed.remove();
// The touch interaction has ended since we will send a click.
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
if (mSendTouchExplorationEndDelayed.isPending()) {
mSendTouchExplorationEndDelayed.forceSendAndRemove();
}
if (mSendTouchInteractionEndDelayed.isPending()) {
mSendTouchInteractionEndDelayed.forceSendAndRemove();
}
int clickLocationX;
int clickLocationY;
@@ -1416,7 +1451,7 @@ class TouchExplorer implements EventStreamTransformation {
mLongPressingPointerDeltaX = (int) mEvent.getX(pointerIndex) - clickLocationX;
mLongPressingPointerDeltaY = (int) mEvent.getY(pointerIndex) - clickLocationY;
sendExitEventsIfNeeded(mPolicyFlags);
sendHoverExitAndTouchExplorationGestureEndIfNeeded(mPolicyFlags);
mCurrentState = STATE_DELEGATING;
sendDownForAllActiveNotInjectedPointers(mEvent, mPolicyFlags);
@@ -1445,7 +1480,6 @@ class TouchExplorer implements EventStreamTransformation {
private MotionEvent mPrototype;
private int mPointerIdBits;
private int mPolicyFlags;
private boolean mTouchExplorationInProgress;
public SendHoverDelayed(int hoverAction, boolean gestureStarted) {
mHoverAction = hoverAction;
@@ -1456,7 +1490,6 @@ class TouchExplorer implements EventStreamTransformation {
int pointerIdBits, int policyFlags) {
remove();
mPrototype = MotionEvent.obtain(prototype);
mTouchExplorationInProgress = touchExplorationInProgress;
mPointerIdBits = pointerIdBits;
mPolicyFlags = policyFlags;
mHandler.postDelayed(this, mDetermineUserIntentTimeout);
@@ -1493,7 +1526,6 @@ class TouchExplorer implements EventStreamTransformation {
mPrototype = null;
mPointerIdBits = -1;
mPolicyFlags = 0;
mTouchExplorationInProgress = false;
}
public void forceSendAndRemove() {
@@ -1510,22 +1542,15 @@ class TouchExplorer implements EventStreamTransformation {
Slog.d(LOG_TAG_SEND_HOVER_DELAYED, mGestureStarted ?
"touchExplorationGestureStarted" : "touchExplorationGestureEnded");
}
if (mTouchExplorationInProgress) {
if (mGestureStarted) {
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
} else {
mTouchExplorationGestureEnded = true;
mTouchInteractionEnded = true;
if (!mSendInteractionEndEventsDelayed.isPending()) {
mSendInteractionEndEventsDelayed.post();
}
}
if (mGestureStarted) {
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_START);
} else {
if (!mGestureStarted) {
mTouchInteractionEnded = true;
if (!mSendInteractionEndEventsDelayed.isPending()) {
mSendInteractionEndEventsDelayed.post();
}
if (!mSendTouchExplorationEndDelayed.isPending()) {
mSendTouchExplorationEndDelayed.post();
}
if (mSendTouchInteractionEndDelayed.isPending()) {
mSendTouchInteractionEndDelayed.remove();
mSendTouchInteractionEndDelayed.post();
}
}
sendMotionEvent(mPrototype, mHoverAction, mPointerIdBits, mPolicyFlags);
@@ -1533,14 +1558,21 @@ class TouchExplorer implements EventStreamTransformation {
}
}
private class SendInteractionEndEventsDelayed implements Runnable {
private class SendAccessibilityEventDelayed implements Runnable {
private final int mEventType;
private final int mDelay;
public SendAccessibilityEventDelayed(int eventType, int delay) {
mEventType = eventType;
mDelay = delay;
}
public void remove() {
mHandler.removeCallbacks(this);
}
public void post() {
mHandler.postDelayed(this, SEND_INTERACTION_END_EVENTS_TIMEOUT);
mHandler.postDelayed(this, mDelay);
}
public boolean isPending() {
@@ -1556,14 +1588,7 @@ class TouchExplorer implements EventStreamTransformation {
@Override
public void run() {
if (mTouchExplorationGestureEnded) {
mTouchExplorationGestureEnded = false;
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_EXPLORATION_GESTURE_END);
}
if (mTouchInteractionEnded) {
mTouchInteractionEnded = false;
sendAccessibilityEvent(AccessibilityEvent.TYPE_TOUCH_INTERACTION_END);
}
sendAccessibilityEvent(mEventType);
}
}