mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Set event category for touch events on Android
Summary: Updates event category deduction to match iOS implementation. The event priority is used by concurrent mode to prioritize certain events, where Cxx part already assigns the correct priority based on the `ContinuousStart` -> `ContinuousEnd` spans. These spans can be deduced from the touch events, which we do in this implementation. All events that can be "coalesced" (dispatched through `invokeUnique`) are assigned `Continuous` by default in Fabric core, so scroll/slider change events will never be discrete. Changelog: [Internal] Add category deduction to Android touch events Reviewed By: mdvacca Differential Revision: D31233233 fbshipit-source-id: f5b039aa137f1b4d2e2b15578bfc29ab6903a081
This commit is contained in:
committed by
Facebook GitHub Bot
parent
bf4c6b3606
commit
155a1a8ac9
@@ -54,6 +54,7 @@ import com.facebook.react.common.build.ReactBuildConfig;
|
||||
import com.facebook.react.common.mapbuffer.ReadableMapBuffer;
|
||||
import com.facebook.react.config.ReactFeatureFlags;
|
||||
import com.facebook.react.fabric.events.EventBeatManager;
|
||||
import com.facebook.react.fabric.events.EventCategoryDef;
|
||||
import com.facebook.react.fabric.events.EventEmitterWrapper;
|
||||
import com.facebook.react.fabric.events.FabricEventEmitter;
|
||||
import com.facebook.react.fabric.mounting.MountItemDispatcher;
|
||||
@@ -829,6 +830,23 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
receiveEvent(surfaceId, reactTag, eventName, false, 0, params);
|
||||
}
|
||||
|
||||
public void receiveEvent(
|
||||
int surfaceId,
|
||||
int reactTag,
|
||||
String eventName,
|
||||
boolean canCoalesceEvent,
|
||||
int customCoalesceKey,
|
||||
@Nullable WritableMap params) {
|
||||
receiveEvent(
|
||||
surfaceId,
|
||||
reactTag,
|
||||
eventName,
|
||||
canCoalesceEvent,
|
||||
customCoalesceKey,
|
||||
params,
|
||||
EventCategoryDef.UNSPECIFIED);
|
||||
}
|
||||
|
||||
/**
|
||||
* receiveEvent API that emits an event to C++. If `canCoalesceEvent` is true, that signals that
|
||||
* C++ may coalesce the event optionally. Otherwise, coalescing can happen in Java before
|
||||
@@ -842,6 +860,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
* @param canCoalesceEvent
|
||||
* @param customCoalesceKey
|
||||
* @param params
|
||||
* @param eventCategory
|
||||
*/
|
||||
public void receiveEvent(
|
||||
int surfaceId,
|
||||
@@ -849,7 +868,8 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
String eventName,
|
||||
boolean canCoalesceEvent,
|
||||
int customCoalesceKey,
|
||||
@Nullable WritableMap params) {
|
||||
@Nullable WritableMap params,
|
||||
@EventCategoryDef int eventCategory) {
|
||||
if (ReactBuildConfig.DEBUG && surfaceId == View.NO_ID) {
|
||||
FLog.d(TAG, "Emitted event without surfaceId: [%d] %s", reactTag, eventName);
|
||||
}
|
||||
@@ -870,7 +890,7 @@ public class FabricUIManager implements UIManager, LifecycleEventListener {
|
||||
if (canCoalesceEvent) {
|
||||
eventEmitter.invokeUnique(eventName, params, customCoalesceKey);
|
||||
} else {
|
||||
eventEmitter.invoke(eventName, params);
|
||||
eventEmitter.invoke(eventName, params, eventCategory);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-2
@@ -48,12 +48,15 @@ public class EventEmitterWrapper {
|
||||
* @param eventName {@link String} name of the event to execute.
|
||||
* @param params {@link WritableMap} payload of the event
|
||||
*/
|
||||
public synchronized void invoke(@NonNull String eventName, @Nullable WritableMap params) {
|
||||
public synchronized void invoke(
|
||||
@NonNull String eventName,
|
||||
@Nullable WritableMap params,
|
||||
@EventCategoryDef int eventCategory) {
|
||||
if (!isValid()) {
|
||||
return;
|
||||
}
|
||||
NativeMap payload = params == null ? new WritableNativeMap() : (NativeMap) params;
|
||||
invokeEvent(eventName, payload, EventCategoryDef.UNSPECIFIED);
|
||||
invokeEvent(eventName, payload, eventCategory);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+30
-5
@@ -10,8 +10,6 @@ package com.facebook.react.fabric.events;
|
||||
import static com.facebook.react.uimanager.events.TouchesHelper.CHANGED_TOUCHES_KEY;
|
||||
import static com.facebook.react.uimanager.events.TouchesHelper.TARGET_KEY;
|
||||
import static com.facebook.react.uimanager.events.TouchesHelper.TARGET_SURFACE_KEY;
|
||||
import static com.facebook.react.uimanager.events.TouchesHelper.TOP_TOUCH_CANCEL_KEY;
|
||||
import static com.facebook.react.uimanager.events.TouchesHelper.TOP_TOUCH_END_KEY;
|
||||
import static com.facebook.react.uimanager.events.TouchesHelper.TOUCHES_KEY;
|
||||
|
||||
import android.util.Pair;
|
||||
@@ -25,6 +23,7 @@ import com.facebook.react.bridge.WritableNativeArray;
|
||||
import com.facebook.react.bridge.WritableNativeMap;
|
||||
import com.facebook.react.fabric.FabricUIManager;
|
||||
import com.facebook.react.uimanager.events.RCTModernEventEmitter;
|
||||
import com.facebook.react.uimanager.events.TouchEventType;
|
||||
import com.facebook.systrace.Systrace;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
@@ -71,15 +70,23 @@ public class FabricEventEmitter implements RCTModernEventEmitter {
|
||||
@NonNull String eventTopLevelType,
|
||||
@NonNull WritableArray touches,
|
||||
@NonNull WritableArray changedIndices) {
|
||||
Systrace.beginSection(
|
||||
Systrace.TRACE_TAG_REACT_JAVA_BRIDGE,
|
||||
"FabricEventEmitter.receiveTouches('" + eventTopLevelType + "')");
|
||||
|
||||
boolean isPointerEndEvent =
|
||||
TouchEventType.END.getJsName().equalsIgnoreCase(eventTopLevelType)
|
||||
|| TouchEventType.CANCEL.getJsName().equalsIgnoreCase(eventTopLevelType);
|
||||
|
||||
Pair<WritableArray, WritableArray> result =
|
||||
TOP_TOUCH_END_KEY.equalsIgnoreCase(eventTopLevelType)
|
||||
|| TOP_TOUCH_CANCEL_KEY.equalsIgnoreCase(eventTopLevelType)
|
||||
isPointerEndEvent
|
||||
? removeTouchesAtIndices(touches, changedIndices)
|
||||
: touchSubsequence(touches, changedIndices);
|
||||
|
||||
WritableArray changedTouches = result.first;
|
||||
touches = result.second;
|
||||
|
||||
int eventCategory = getTouchCategory(eventTopLevelType);
|
||||
for (int jj = 0; jj < changedTouches.size(); jj++) {
|
||||
WritableMap touch = getWritableMap(changedTouches.getMap(jj));
|
||||
// Touch objects can fulfill the role of `DOM` `Event` objects if we set
|
||||
@@ -97,8 +104,11 @@ public class FabricEventEmitter implements RCTModernEventEmitter {
|
||||
rootNodeID = targetReactTag;
|
||||
}
|
||||
|
||||
receiveEvent(targetSurfaceId, rootNodeID, eventTopLevelType, false, 0, touch);
|
||||
mUIManager.receiveEvent(
|
||||
targetSurfaceId, rootNodeID, eventTopLevelType, false, 0, touch, eventCategory);
|
||||
}
|
||||
|
||||
Systrace.endSection(Systrace.TRACE_TAG_REACT_JAVA_BRIDGE);
|
||||
}
|
||||
|
||||
/** TODO T31905686 optimize this to avoid copying arrays */
|
||||
@@ -174,4 +184,19 @@ public class FabricEventEmitter implements RCTModernEventEmitter {
|
||||
map.merge(readableMap);
|
||||
return map;
|
||||
}
|
||||
|
||||
@EventCategoryDef
|
||||
private static int getTouchCategory(String touchEventType) {
|
||||
int category = EventCategoryDef.UNSPECIFIED;
|
||||
if (TouchEventType.MOVE.getJsName().equals(touchEventType)) {
|
||||
category = EventCategoryDef.CONTINUOUS;
|
||||
} else if (TouchEventType.START.getJsName().equals(touchEventType)) {
|
||||
category = EventCategoryDef.CONTINUOUS_START;
|
||||
} else if (TouchEventType.END.getJsName().equals(touchEventType)
|
||||
|| TouchEventType.CANCEL.getJsName().equals(touchEventType)) {
|
||||
category = EventCategoryDef.CONTINUOUS_END;
|
||||
}
|
||||
|
||||
return category;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,5 +27,12 @@ public interface RCTEventEmitter extends JavaScriptModule {
|
||||
@Deprecated
|
||||
void receiveEvent(int targetTag, String eventName, @Nullable WritableMap event);
|
||||
|
||||
/**
|
||||
* Receive and process touches
|
||||
*
|
||||
* @param eventName JS event name
|
||||
* @param touches active pointers data
|
||||
* @param changedIndices indices of changed pointers
|
||||
*/
|
||||
void receiveTouches(String eventName, WritableArray touches, WritableArray changedIndices);
|
||||
}
|
||||
|
||||
+15
-16
@@ -9,23 +9,22 @@ package com.facebook.react.uimanager.events;
|
||||
|
||||
/** Touch event types that JS module RCTEventEmitter can understand */
|
||||
public enum TouchEventType {
|
||||
START,
|
||||
END,
|
||||
MOVE,
|
||||
CANCEL;
|
||||
START("topTouchStart"),
|
||||
END("topTouchEnd"),
|
||||
MOVE("topTouchMove"),
|
||||
CANCEL("topTouchCancel");
|
||||
|
||||
private final String mJsName;
|
||||
|
||||
TouchEventType(String jsName) {
|
||||
mJsName = jsName;
|
||||
}
|
||||
|
||||
public String getJsName() {
|
||||
return mJsName;
|
||||
}
|
||||
|
||||
public static String getJSEventName(TouchEventType type) {
|
||||
switch (type) {
|
||||
case START:
|
||||
return "topTouchStart";
|
||||
case END:
|
||||
return "topTouchEnd";
|
||||
case MOVE:
|
||||
return "topTouchMove";
|
||||
case CANCEL:
|
||||
return "topTouchCancel";
|
||||
default:
|
||||
throw new IllegalArgumentException("Unexpected type " + type);
|
||||
}
|
||||
return type.getJsName();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,6 @@ public class TouchesHelper {
|
||||
public static final String TARGET_KEY = "target";
|
||||
public static final String CHANGED_TOUCHES_KEY = "changedTouches";
|
||||
public static final String TOUCHES_KEY = "touches";
|
||||
public static final String TOP_TOUCH_END_KEY = "topTouchEnd";
|
||||
public static final String TOP_TOUCH_CANCEL_KEY = "topTouchCancel";
|
||||
private static final String PAGE_X_KEY = "pageX";
|
||||
private static final String PAGE_Y_KEY = "pageY";
|
||||
private static final String TIMESTAMP_KEY = "timestamp";
|
||||
|
||||
Reference in New Issue
Block a user