/**
* 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 javax.annotation.Nullable;
import android.support.v4.util.Pools;
import android.view.MotionEvent;
import com.facebook.infer.annotation.Assertions;
/**
* 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 static final int TOUCH_EVENTS_POOL_SIZE = 3;
private static final Pools.SynchronizedPool<TouchEvent> EVENTS_POOL =
new Pools.SynchronizedPool<>(TOUCH_EVENTS_POOL_SIZE);
public static TouchEvent obtain(
int viewTag,
TouchEventType touchEventType,
MotionEvent motionEventToCopy,
float viewX,
float viewY,
TouchEventCoalescingKeyHelper touchEventCoalescingKeyHelper) {
TouchEvent event = EVENTS_POOL.acquire();
if (event == null) {
event = new TouchEvent();
}
event.init(
viewTag,
touchEventType,
motionEventToCopy,
viewX,
viewY,
touchEventCoalescingKeyHelper);
return event;
}
private @Nullable MotionEvent mMotionEvent;
private @Nullable TouchEventType mTouchEventType;
private short mCoalescingKey;
// Coordinates in the ViewTag coordinate space
private float mViewX;
private float mViewY;
private TouchEvent() {
}
private void init(
int viewTag,
TouchEventType touchEventType,
MotionEvent motionEventToCopy,
float viewX,
float viewY,
TouchEventCoalescingKeyHelper touchEventCoalescingKeyHelper) {
super.init(viewTag);
short coalescingKey = 0;
int action = (motionEventToCopy.getAction() & MotionEvent.ACTION_MASK);
switch (action) {
case MotionEvent.ACTION_DOWN:
touchEventCoalescingKeyHelper.addCoalescingKey(motionEventToCopy.getDownTime());
break;
case MotionEvent.ACTION_UP:
touchEventCoalescingKeyHelper.removeCoalescingKey(motionEventToCopy.getDownTime());
break;
case MotionEvent.ACTION_POINTER_DOWN:
case MotionEvent.ACTION_POINTER_UP:
touchEventCoalescingKeyHelper.incrementCoalescingKey(motionEventToCopy.getDownTime());
break;
case MotionEvent.ACTION_MOVE:
coalescingKey =
touchEventCoalescingKeyHelper.getCoalescingKey(motionEventToCopy.getDownTime());
break;
case MotionEvent.ACTION_CANCEL:
touchEventCoalescingKeyHelper.removeCoalescingKey(motionEventToCopy.getDownTime());
break;
default:
throw new RuntimeException("Unhandled MotionEvent action: " + action);
}
mTouchEventType = touchEventType;
mMotionEvent = MotionEvent.obtain(motionEventToCopy);
mCoalescingKey = coalescingKey;
mViewX = viewX;
mViewY = viewY;
}
@Override
public void onDispose() {
Assertions.assertNotNull(mMotionEvent).recycle();
mMotionEvent = null;
EVENTS_POOL.release(this);
}
@Override
public String getEventName() {
return Assertions.assertNotNull(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 (Assertions.assertNotNull(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,
Assertions.assertNotNull(mTouchEventType),
getViewTag(),
this);
}
public MotionEvent getMotionEvent() {
Assertions.assertNotNull(mMotionEvent);
return mMotionEvent;
}
public float getViewX() {
return mViewX;
}
public float getViewY() {
return mViewY;
}
}