/**
* Copyright (c) 2015-present, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.react.uimanager.events;
import android.view.MotionEvent;
/**
* An event representing the start, end or movement of a touch. Corresponds to a single
* {@link android.view.MotionEvent}.
*
* TouchEvent coalescing can happen for move events if two move events have the same target view and
* coalescing key. See {@link TouchEventCoalescingKeyHelper} for more information about how these
* coalescing keys are determined.
*/
public class TouchEvent extends Event<TouchEvent> {
private final MotionEvent mMotionEvent;
private final TouchEventType mTouchEventType;
private final short mCoalescingKey;
public TouchEvent(
int viewTag,
long timestampMs,
TouchEventType touchEventType,
MotionEvent motionEventToCopy) {
super(viewTag, timestampMs);
mTouchEventType = touchEventType;
mMotionEvent = MotionEvent.obtain(motionEventToCopy);
short coalescingKey = 0;
int action = (mMotionEvent.getAction() & MotionEvent.ACTION_MASK);
switch (action) {
case MotionEvent.ACTION_DOWN:
TouchEventCoalescingKeyHelper.addCoalescingKey(mMotionEvent.getDownTime());
break;
case MotionEvent.ACTION_UP:
TouchEventCoalescingKeyHelper.removeCoalescingKey(mMotionEvent.getDownTime());
break;
case MotionEvent.ACTION_POINTER_DOWN:
case MotionEvent.ACTION_POINTER_UP:
TouchEventCoalescingKeyHelper.incrementCoalescingKey(mMotionEvent.getDownTime());
break;
case MotionEvent.ACTION_MOVE:
coalescingKey = TouchEventCoalescingKeyHelper.getCoalescingKey(mMotionEvent.getDownTime());
break;
case MotionEvent.ACTION_CANCEL:
TouchEventCoalescingKeyHelper.removeCoalescingKey(mMotionEvent.getDownTime());
break;
default:
throw new RuntimeException("Unhandled MotionEvent action: " + action);
}
mCoalescingKey = coalescingKey;
}
@Override
public String getEventName() {
return mTouchEventType.getJSEventName();
}
@Override
public boolean canCoalesce() {
// We can coalesce move events but not start/end events. Coalescing move events should probably
// append historical move data like MotionEvent batching does. This is left as an exercise for
// the reader.
switch (mTouchEventType) {
case START:
case END:
case CANCEL:
return false;
case MOVE:
return true;
default:
throw new RuntimeException("Unknown touch event type: " + mTouchEventType);
}
}
@Override
public short getCoalescingKey() {
return mCoalescingKey;
}
@Override
public void dispatch(RCTEventEmitter rctEventEmitter) {
TouchesHelper.sendTouchEvent(
rctEventEmitter,
mTouchEventType,
getViewTag(),
mMotionEvent);
}
@Override
public void dispose() {
mMotionEvent.recycle();
}
}