@react-native-oh-tpl/react-native-gesture-handler 2.14.1-2.14.12 → 2.14.1-2.14.14
Sign up to get free protection for your applications and to get access to all the features.
- package/harmony/gesture_handler/BuildProfile.ets +1 -1
- package/harmony/gesture_handler/index.ets +1 -2
- package/harmony/gesture_handler/oh-package-lock.json5 +1 -1
- package/harmony/gesture_handler/oh-package.json5 +3 -3
- package/harmony/gesture_handler/src/main/cpp/CMakeLists.txt +1 -1
- package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.h +9 -18
- package/harmony/gesture_handler/src/main/cpp/RnohReactNativeHarmonyGestureHandlerPackage.cpp +157 -0
- package/harmony/gesture_handler/src/main/cpp/RnohReactNativeHarmonyGestureHandlerPackage.h +21 -0
- package/harmony/gesture_handler/src/main/cpp/componentInstances/RNGestureHandlerButtonComponentInstance.h +16 -16
- package/harmony/gesture_handler/src/main/cpp/componentInstances/RNGestureHandlerRootViewComponentInstance.h +202 -199
- package/harmony/gesture_handler/src/main/ets/RNOHPackage.ets +17 -0
- package/harmony/gesture_handler/src/main/ets/core/GestureHandler.ts +92 -37
- package/harmony/gesture_handler/src/main/ets/core/GestureHandlerOrchestrator.ts +20 -11
- package/harmony/gesture_handler/src/main/ets/core/GestureHandlerRegistry.ts +31 -3
- package/harmony/gesture_handler/src/main/ets/core/InteractionManager.ts +4 -4
- package/harmony/gesture_handler/src/main/ets/core/Multiset.ts +26 -0
- package/harmony/gesture_handler/src/main/ets/core/RNGHLogger.ts +7 -3
- package/harmony/gesture_handler/src/main/ets/core/ViewRegistry.ts +7 -0
- package/harmony/gesture_handler/src/main/ets/core/index.ts +3 -1
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/FlingGestureHandler.ts +12 -4
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/GestureHandlerFactory.ts +8 -5
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/LongPressGestureHandler.ts +14 -2
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/ManualGestureHandler.ts +9 -1
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/NativeViewGestureHandler.ts +13 -4
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/PanGestureHandler.ts +31 -12
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/PinchGestureHandler.ts +145 -130
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/RotationGestureHandler.ts +9 -1
- package/harmony/gesture_handler/src/main/ets/gesture-handlers/TapGestureHandler.ts +15 -5
- package/harmony/gesture_handler/src/main/ets/rnoh/GestureHandlerPackage.ts +7 -4
- package/harmony/gesture_handler/src/main/ets/rnoh/Logger.ts +74 -16
- package/harmony/gesture_handler/src/main/ets/rnoh/OutgoingEventDispatchers.ts +35 -12
- package/harmony/gesture_handler/src/main/ets/rnoh/RNGHRootViewController.ts +182 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/RNGHView.ts +62 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/{GestureHandlerArkUIAdapter.ts → RNGHViewController.ts} +44 -22
- package/harmony/gesture_handler/src/main/ets/rnoh/RNGHViewRegistry.ts +19 -0
- package/harmony/gesture_handler/src/main/ets/rnoh/RNGestureHandlerModule.ts +130 -95
- package/harmony/gesture_handler/src/main/ets/rnoh/RNOHGestureResponder.ts +0 -9
- package/harmony/gesture_handler/src/main/ets/rnoh/RNOHScrollLocker.ts +1 -8
- package/harmony/gesture_handler.har +0 -0
- package/package.json +7 -3
- package/harmony/gesture_handler/src/main/cpp/GestureHandlerPackage.cpp +0 -149
- package/harmony/gesture_handler/src/main/ets/rnoh/RNGHRootTouchHandlerArkTS.ts +0 -108
- package/harmony/gesture_handler/src/main/ets/rnoh/RNGHRootTouchHandlerCAPI.ts +0 -110
- package/harmony/gesture_handler/src/main/ets/rnoh/RNGestureHandlerButton.ets +0 -38
- package/harmony/gesture_handler/src/main/ets/rnoh/RNGestureHandlerRootView.ets +0 -53
- package/harmony/gesture_handler/src/main/ets/rnoh/View.ts +0 -134
- package/harmony/gesture_handler/src/main/ets/rnoh/ViewRegistry.ts +0 -95
@@ -1,23 +1,71 @@
|
|
1
1
|
import { RNOHContext } from '@rnoh/react-native-openharmony/ts';
|
2
2
|
import { RNGHLogger, RNGHLoggerMessage } from "../core"
|
3
|
+
import hiTrace from "@ohos.hiTraceMeter"
|
3
4
|
|
4
|
-
|
5
|
+
class Tracer {
|
6
|
+
private activeTracesCount: number = 0
|
7
|
+
|
8
|
+
public startTrace(name: string) {
|
9
|
+
/**
|
10
|
+
* hiTrace.startTrace creates a new lane which makes the traces useless
|
11
|
+
*/
|
12
|
+
hiTrace.startTrace(name, 0)
|
13
|
+
this.activeTracesCount++
|
14
|
+
return () => {
|
15
|
+
hiTrace.finishTrace(name, 0)
|
16
|
+
this.activeTracesCount--
|
17
|
+
}
|
18
|
+
}
|
19
|
+
|
20
|
+
public getActiveTracesCount(): number {
|
21
|
+
return this.activeTracesCount
|
22
|
+
}
|
23
|
+
}
|
24
|
+
|
25
|
+
export class DevelopmentRNGHLogger implements RNGHLogger {
|
5
26
|
constructor(
|
6
|
-
|
7
|
-
|
27
|
+
protected rnohLogger: RNOHContext['logger'],
|
28
|
+
protected prefix: string,
|
29
|
+
protected tracer: Tracer = new Tracer(),
|
8
30
|
) {
|
9
31
|
}
|
10
32
|
|
11
33
|
error(msg: string) {
|
12
|
-
this.
|
34
|
+
this.log("error", msg);
|
35
|
+
}
|
36
|
+
|
37
|
+
warn(msg: string) {
|
38
|
+
this.log("warn", msg);
|
13
39
|
}
|
14
40
|
|
15
41
|
info(msg: string) {
|
16
|
-
this.
|
42
|
+
this.log("info", msg);
|
17
43
|
}
|
18
44
|
|
19
45
|
debug(msg: RNGHLoggerMessage) {
|
20
|
-
this.
|
46
|
+
this.log("debug", typeof msg === "string" ? msg : JSON.stringify(msg));
|
47
|
+
}
|
48
|
+
|
49
|
+
protected log(type: "debug" | "info" | "warn" | "error", msg: string, offset: number | undefined = undefined) {
|
50
|
+
this.rnohLogger[type](" ".repeat(offset ?? this.tracer.getActiveTracesCount() * 2),
|
51
|
+
`${this.prefix}: ${this.stringifyMsg(msg)}`)
|
52
|
+
}
|
53
|
+
|
54
|
+
startTracing(): () => void {
|
55
|
+
const startTime = Date.now()
|
56
|
+
const currentOffset = this.tracer.getActiveTracesCount() * 2
|
57
|
+
this.log("debug", "START", currentOffset)
|
58
|
+
const stopTrace = this.tracer.startTrace(this.prefix)
|
59
|
+
return () => {
|
60
|
+
stopTrace()
|
61
|
+
const stopTime = Date.now()
|
62
|
+
const durationInMs = stopTime - startTime
|
63
|
+
if (durationInMs < 16) {
|
64
|
+
this.log("debug", "STOP", currentOffset)
|
65
|
+
} else {
|
66
|
+
this.log("debug", `STOP (${durationInMs} ms)`, currentOffset)
|
67
|
+
}
|
68
|
+
}
|
21
69
|
}
|
22
70
|
|
23
71
|
private stringifyMsg(msg: RNGHLoggerMessage): string {
|
@@ -28,22 +76,32 @@ export class StandardRNGHLogger implements RNGHLogger {
|
|
28
76
|
}
|
29
77
|
}
|
30
78
|
|
31
|
-
|
32
|
-
return new
|
79
|
+
cloneAndJoinPrefix(prefix: string) {
|
80
|
+
return new DevelopmentRNGHLogger(this.rnohLogger, `${this.prefix}::${prefix}`, this.tracer);
|
33
81
|
}
|
34
82
|
}
|
35
83
|
|
36
|
-
export class
|
37
|
-
|
84
|
+
export class ProductionRNGHLogger extends DevelopmentRNGHLogger {
|
85
|
+
override debug(msg: string) {
|
86
|
+
// NOOP
|
38
87
|
}
|
39
88
|
|
40
|
-
|
89
|
+
override cloneAndJoinPrefix(prefix: string) {
|
90
|
+
return new ProductionRNGHLogger(this.rnohLogger, `${this.prefix}::${prefix}`, this.tracer);
|
41
91
|
}
|
42
92
|
|
43
|
-
|
44
|
-
|
93
|
+
override startTracing(): () => void {
|
94
|
+
const startTime = Date.now()
|
95
|
+
const currentOffset = this.tracer.getActiveTracesCount() * 2
|
45
96
|
|
46
|
-
|
47
|
-
return
|
97
|
+
const stopTrace = this.tracer.startTrace(this.prefix)
|
98
|
+
return () => {
|
99
|
+
stopTrace()
|
100
|
+
const stopTime = Date.now()
|
101
|
+
const durationInMs = stopTime - startTime
|
102
|
+
if (durationInMs > 16) {
|
103
|
+
this.log("warn", `STOP (${durationInMs} ms)`, currentOffset)
|
104
|
+
}
|
105
|
+
}
|
48
106
|
}
|
49
|
-
}
|
107
|
+
}
|
@@ -1,71 +1,94 @@
|
|
1
1
|
import { RNInstance } from '@rnoh/react-native-openharmony/ts';
|
2
|
-
import {
|
2
|
+
import {
|
3
|
+
OutgoingEventDispatcher,
|
4
|
+
GestureStateChangeEvent,
|
5
|
+
GestureUpdateEvent,
|
6
|
+
GestureTouchEvent,
|
7
|
+
RNGHLogger
|
8
|
+
} from "../core"
|
3
9
|
|
4
10
|
export class JSEventDispatcher implements OutgoingEventDispatcher {
|
5
|
-
|
11
|
+
private logger: RNGHLogger
|
12
|
+
|
13
|
+
constructor(private rnInstance: RNInstance, logger: RNGHLogger) {
|
14
|
+
this.logger = logger.cloneAndJoinPrefix("JSEventDispatcher")
|
6
15
|
}
|
7
16
|
|
8
17
|
public onGestureHandlerStateChange(event: GestureStateChangeEvent) {
|
9
|
-
this.logger.
|
18
|
+
const stopTracing = this.logger.cloneAndJoinPrefix(`onGestureHandlerStateChange`).startTracing();
|
10
19
|
this.rnInstance.emitDeviceEvent('onGestureHandlerStateChange', event);
|
20
|
+
stopTracing()
|
11
21
|
}
|
12
22
|
|
13
23
|
public onGestureHandlerEvent(
|
14
24
|
event: GestureStateChangeEvent | GestureUpdateEvent | GestureTouchEvent,
|
15
25
|
) {
|
16
|
-
this.logger.
|
26
|
+
const stopTracing = this.logger.cloneAndJoinPrefix(`onGestureHandlerEvent`).startTracing();
|
17
27
|
this.rnInstance.emitDeviceEvent('onGestureHandlerEvent', event);
|
28
|
+
stopTracing()
|
18
29
|
}
|
19
30
|
}
|
20
31
|
|
21
32
|
export class AnimatedEventDispatcher implements OutgoingEventDispatcher {
|
33
|
+
private logger: RNGHLogger
|
34
|
+
|
22
35
|
constructor(
|
23
36
|
private rnInstance: RNInstance,
|
24
|
-
|
37
|
+
logger: RNGHLogger,
|
25
38
|
private viewTag: number,
|
26
|
-
) {
|
39
|
+
) {
|
40
|
+
this.logger = logger.cloneAndJoinPrefix("AnimatedEventDispatcher")
|
41
|
+
}
|
27
42
|
|
28
43
|
public onGestureHandlerStateChange(event: GestureStateChangeEvent) {
|
29
|
-
this.logger.
|
44
|
+
const stopTracing = this.logger.cloneAndJoinPrefix(`onGestureHandlerStateChange`).startTracing()
|
30
45
|
this.rnInstance.emitDeviceEvent('onGestureHandlerStateChange', event);
|
46
|
+
stopTracing()
|
31
47
|
}
|
32
48
|
|
33
49
|
public onGestureHandlerEvent(
|
34
50
|
event: GestureStateChangeEvent | GestureUpdateEvent | GestureTouchEvent,
|
35
51
|
) {
|
36
|
-
this.logger.
|
52
|
+
const stopTracing = this.logger.cloneAndJoinPrefix(`onGestureHandlerEvent`).startTracing();
|
37
53
|
this.rnInstance.emitComponentEvent(
|
38
54
|
this.viewTag,
|
39
55
|
'onGestureHandlerEvent',
|
40
56
|
event,
|
41
57
|
);
|
58
|
+
stopTracing()
|
42
59
|
}
|
43
60
|
}
|
44
61
|
|
45
62
|
export class ReanimatedEventDispatcher implements OutgoingEventDispatcher {
|
63
|
+
private logger: RNGHLogger
|
64
|
+
|
46
65
|
constructor(
|
47
66
|
private rnInstance: RNInstance,
|
48
|
-
|
67
|
+
logger: RNGHLogger,
|
49
68
|
private viewTag: number,
|
50
|
-
) {
|
69
|
+
) {
|
70
|
+
this.logger = logger.cloneAndJoinPrefix("ReanimatedEventDispatcher")
|
71
|
+
}
|
51
72
|
|
52
73
|
public onGestureHandlerStateChange(event: GestureStateChangeEvent) {
|
53
|
-
this.logger.
|
74
|
+
const stopTracing = this.logger.cloneAndJoinPrefix(`onGestureHandlerStateChange`).startTracing();
|
54
75
|
this.rnInstance.emitComponentEvent(
|
55
76
|
this.viewTag,
|
56
77
|
'onGestureHandlerStateChange',
|
57
78
|
event,
|
58
79
|
);
|
80
|
+
stopTracing()
|
59
81
|
}
|
60
82
|
|
61
83
|
public onGestureHandlerEvent(
|
62
84
|
event: GestureStateChangeEvent | GestureUpdateEvent | GestureTouchEvent,
|
63
85
|
) {
|
64
|
-
this.logger.
|
86
|
+
const stopTracing = this.logger.cloneAndJoinPrefix(`onGestureHandlerEvent`).startTracing();
|
65
87
|
this.rnInstance.emitComponentEvent(
|
66
88
|
this.viewTag,
|
67
89
|
'onGestureHandlerEvent',
|
68
90
|
event,
|
69
91
|
);
|
92
|
+
stopTracing()
|
70
93
|
}
|
71
94
|
}
|
@@ -0,0 +1,182 @@
|
|
1
|
+
import { TouchEvent as TouchEventArkTS, TouchType, TouchObject } from './types';
|
2
|
+
import { RNGHLogger, View, Multiset, GestureHandlerRegistry } from '../core';
|
3
|
+
import { RawTouchableView } from "./RNGHView"
|
4
|
+
import { RNGHViewController } from './RNGHViewController';
|
5
|
+
|
6
|
+
type RawTouchPoint = {
|
7
|
+
pointerId: number;
|
8
|
+
windowX: number;
|
9
|
+
windowY: number;
|
10
|
+
};
|
11
|
+
|
12
|
+
export type RawTouchEvent = {
|
13
|
+
action: number;
|
14
|
+
actionTouch: RawTouchPoint;
|
15
|
+
touchPoints: RawTouchPoint[];
|
16
|
+
sourceType: number;
|
17
|
+
timestamp: number;
|
18
|
+
/** TouchableViews is a list of views from the root to the leaf which contain within their boundaries the touch point specified by `actionTouch`. */
|
19
|
+
touchableViews: RawTouchableView[]
|
20
|
+
};
|
21
|
+
|
22
|
+
|
23
|
+
const areRawTouchPointsEqual = (a: RawTouchPoint, b: RawTouchPoint) =>
|
24
|
+
a.pointerId === b.pointerId &&
|
25
|
+
a.windowX === b.windowX &&
|
26
|
+
a.windowY === b.windowY;
|
27
|
+
|
28
|
+
|
29
|
+
export class RNGHRootViewController {
|
30
|
+
private logger: RNGHLogger;
|
31
|
+
// This multiset keeps track of touchable views that were detected
|
32
|
+
// at the beginning of the gesture to ensure they aren't overridden
|
33
|
+
// during move touch events, which could prevent the gesture handler
|
34
|
+
// from updating its state correctly.
|
35
|
+
private touchableViewsMultiset: Multiset<View> = new Multiset();
|
36
|
+
private viewControllerByViewTag: Map<number, RNGHViewController> =
|
37
|
+
new Map(); // TODO: remove entry when view is removed
|
38
|
+
/**
|
39
|
+
* A view is ACTIVE, if it recently received POINTER_DOWN event
|
40
|
+
*/
|
41
|
+
private activeViewTags = new Set<number>();
|
42
|
+
|
43
|
+
constructor(
|
44
|
+
logger: RNGHLogger,
|
45
|
+
private gestureHandlerRegistry: GestureHandlerRegistry
|
46
|
+
) {
|
47
|
+
this.logger = logger.cloneAndJoinPrefix('RNGHRootTouchHandlerCAPI');
|
48
|
+
}
|
49
|
+
|
50
|
+
handleTouch(rawTouchEvent: RawTouchEvent, touchableViews: View[]) {
|
51
|
+
/**
|
52
|
+
* NOTE: TouchEventArkTS was used in ArkTS RNOH architecture. Currently only C-API architecture is supported.
|
53
|
+
*/
|
54
|
+
const touchEvent = rawTouchEventToTouchEventArkTS(rawTouchEvent);
|
55
|
+
if (touchEvent.type === TouchType.Down) {
|
56
|
+
touchableViews.forEach(view => this.touchableViewsMultiset.add(view));
|
57
|
+
}
|
58
|
+
const e = touchEvent;
|
59
|
+
if (e.type === TouchType.Down) {
|
60
|
+
this.activeViewTags.clear();
|
61
|
+
}
|
62
|
+
const views = touchableViews
|
63
|
+
for (const view of views) {
|
64
|
+
for (const handler of this.gestureHandlerRegistry.getGestureHandlersByViewTag(
|
65
|
+
view.getTag(),
|
66
|
+
)) {
|
67
|
+
this.logger.info(
|
68
|
+
`Found GestureHandler ${handler.getTag()} for view ${view.getTag()}`,
|
69
|
+
);
|
70
|
+
|
71
|
+
// create view touch handler if necessary
|
72
|
+
if (!this.viewControllerByViewTag.has(view.getTag())) {
|
73
|
+
this.viewControllerByViewTag.set(
|
74
|
+
view.getTag(),
|
75
|
+
new RNGHViewController(
|
76
|
+
view,
|
77
|
+
this.logger,
|
78
|
+
),
|
79
|
+
);
|
80
|
+
}
|
81
|
+
|
82
|
+
// attach handler (there might be multiple handlers per view)
|
83
|
+
this.viewControllerByViewTag.get(view.getTag())!.attachGestureHandler(handler) // TODO: detachGestureHandler
|
84
|
+
|
85
|
+
// register active view tag
|
86
|
+
if (e.type === TouchType.Down) {
|
87
|
+
this.activeViewTags.add(view.getTag());
|
88
|
+
}
|
89
|
+
}
|
90
|
+
}
|
91
|
+
|
92
|
+
// send touch to gesture handlers, prioritize handling touch events for child components
|
93
|
+
if (this.activeViewTags.size > 0) {
|
94
|
+
const tags = Array.from(this.activeViewTags);
|
95
|
+
for (let i = tags.length - 1; i >= 0; i--) {
|
96
|
+
const tag = tags[i];
|
97
|
+
const viewController = this.viewControllerByViewTag.get(tag);
|
98
|
+
if (viewController) {
|
99
|
+
viewController.handleTouch(e);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
}
|
103
|
+
|
104
|
+
|
105
|
+
if (touchEvent.type === TouchType.Up || touchEvent.type === TouchType.Cancel) {
|
106
|
+
touchableViews.forEach(view => this.touchableViewsMultiset.remove(view));
|
107
|
+
}
|
108
|
+
}
|
109
|
+
|
110
|
+
cancelTouches() {
|
111
|
+
for (const activeViewTag of this.activeViewTags) {
|
112
|
+
this.gestureHandlerRegistry.getGestureHandlersByViewTag(activeViewTag).forEach(gh => {
|
113
|
+
gh.cancel()
|
114
|
+
gh.reset()
|
115
|
+
})
|
116
|
+
}
|
117
|
+
}
|
118
|
+
}
|
119
|
+
|
120
|
+
|
121
|
+
const CACHED_RAW_TOUCH_POINT_BY_POINTER_ID = new Map<number, RawTouchPoint>();
|
122
|
+
let LAST_CHANGED_POINTER_ID: number | null = null;
|
123
|
+
const MAX_CACHE_SIZE = 10;
|
124
|
+
|
125
|
+
function rawTouchEventToTouchEventArkTS(raw: RawTouchEvent): TouchEventArkTS {
|
126
|
+
const touchType = touchTypeFromAction(raw.action);
|
127
|
+
const actionTouch = raw.actionTouch;
|
128
|
+
|
129
|
+
let lastChangedTouch: RawTouchPoint = actionTouch;
|
130
|
+
if (CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.has(actionTouch.pointerId)) {
|
131
|
+
if (!areRawTouchPointsEqual(actionTouch,
|
132
|
+
CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.get(actionTouch.pointerId) as RawTouchPoint)) {
|
133
|
+
LAST_CHANGED_POINTER_ID = actionTouch.pointerId;
|
134
|
+
CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.set(actionTouch.pointerId, actionTouch);
|
135
|
+
}
|
136
|
+
} else {
|
137
|
+
// remove first element if the cache is full
|
138
|
+
if (CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.size >= MAX_CACHE_SIZE) {
|
139
|
+
CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.delete(CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.keys().next().value);
|
140
|
+
}
|
141
|
+
LAST_CHANGED_POINTER_ID = actionTouch.pointerId;
|
142
|
+
CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.set(actionTouch.pointerId, actionTouch);
|
143
|
+
}
|
144
|
+
lastChangedTouch = CACHED_RAW_TOUCH_POINT_BY_POINTER_ID.get(LAST_CHANGED_POINTER_ID as number) as RawTouchPoint
|
145
|
+
return {
|
146
|
+
type: touchTypeFromAction(raw.action),
|
147
|
+
touches: raw.touchPoints.map(tp =>
|
148
|
+
touchObjectFromTouchPoint(tp, touchType),
|
149
|
+
),
|
150
|
+
changedTouches: [
|
151
|
+
touchObjectFromTouchPoint(lastChangedTouch, touchType),
|
152
|
+
],
|
153
|
+
timestamp: raw.timestamp / Math.pow(10, 6),
|
154
|
+
};
|
155
|
+
}
|
156
|
+
|
157
|
+
function touchTypeFromAction(action: number): TouchType {
|
158
|
+
switch (action) {
|
159
|
+
case 1:
|
160
|
+
return TouchType.Down;
|
161
|
+
case 2:
|
162
|
+
return TouchType.Move;
|
163
|
+
case 3:
|
164
|
+
return TouchType.Up;
|
165
|
+
default:
|
166
|
+
return TouchType.Cancel;
|
167
|
+
}
|
168
|
+
}
|
169
|
+
|
170
|
+
function touchObjectFromTouchPoint(
|
171
|
+
touchPoint: RawTouchPoint,
|
172
|
+
touchType: TouchType,
|
173
|
+
): TouchObject {
|
174
|
+
return {
|
175
|
+
id: touchPoint.pointerId,
|
176
|
+
windowX: touchPoint.windowX,
|
177
|
+
windowY: touchPoint.windowY,
|
178
|
+
x: touchPoint.windowX,
|
179
|
+
y: touchPoint.windowY,
|
180
|
+
type: touchType,
|
181
|
+
};
|
182
|
+
}
|
@@ -0,0 +1,62 @@
|
|
1
|
+
import { View, BoundingBox } from "../core"
|
2
|
+
|
3
|
+
|
4
|
+
export type RawTouchableView = {
|
5
|
+
tag: number,
|
6
|
+
/**
|
7
|
+
* Relative to application window.
|
8
|
+
*/
|
9
|
+
x: number,
|
10
|
+
/**
|
11
|
+
* Relative to application window.
|
12
|
+
*/
|
13
|
+
y: number,
|
14
|
+
width: number,
|
15
|
+
height: number,
|
16
|
+
buttonRole: boolean,
|
17
|
+
}
|
18
|
+
|
19
|
+
export class RNGHView implements View {
|
20
|
+
private tag: number
|
21
|
+
private buttonRole: boolean
|
22
|
+
private boundingBox: BoundingBox
|
23
|
+
|
24
|
+
constructor({ tag, buttonRole, ...boundingBox }: RawTouchableView) {
|
25
|
+
this.tag = tag
|
26
|
+
this.buttonRole = buttonRole
|
27
|
+
this.boundingBox = boundingBox
|
28
|
+
}
|
29
|
+
|
30
|
+
getTag(): number {
|
31
|
+
return this.tag
|
32
|
+
}
|
33
|
+
|
34
|
+
getBoundingRect(): BoundingBox {
|
35
|
+
return { ...this.boundingBox }
|
36
|
+
}
|
37
|
+
|
38
|
+
isPositionInBounds({ x, y }: {
|
39
|
+
x: number;
|
40
|
+
y: number
|
41
|
+
}): boolean {
|
42
|
+
const rect = this.getBoundingRect();
|
43
|
+
return (
|
44
|
+
x >= rect.x &&
|
45
|
+
x <= rect.x + rect.width &&
|
46
|
+
y >= rect.y &&
|
47
|
+
y <= rect.y + rect.height
|
48
|
+
);
|
49
|
+
}
|
50
|
+
|
51
|
+
updateBoundingBox(boundingBox: BoundingBox) {
|
52
|
+
this.boundingBox = boundingBox
|
53
|
+
}
|
54
|
+
|
55
|
+
setButtonRole(buttonRole: boolean) {
|
56
|
+
this.buttonRole = buttonRole
|
57
|
+
}
|
58
|
+
|
59
|
+
hasButtonRole(): boolean {
|
60
|
+
return this.buttonRole
|
61
|
+
}
|
62
|
+
}
|
@@ -11,15 +11,16 @@ import {
|
|
11
11
|
} from '../core';
|
12
12
|
import { TouchEvent, TouchType, TouchObject } from './types';
|
13
13
|
|
14
|
-
|
14
|
+
|
15
|
+
export class RNGHViewController {
|
15
16
|
private activePointerIds = new Set<number>();
|
16
|
-
private
|
17
|
+
private pointerIdsInBounds = new Set<number>();
|
17
18
|
private gestureHandlers = new Set<GestureHandler>();
|
18
19
|
private view: View;
|
19
20
|
private logger: RNGHLogger;
|
20
21
|
|
21
22
|
constructor(view: View, logger: RNGHLogger) {
|
22
|
-
this.logger = logger.
|
23
|
+
this.logger = logger.cloneAndJoinPrefix(`RNGHViewTouchHandler`)
|
23
24
|
this.view = view;
|
24
25
|
}
|
25
26
|
|
@@ -28,19 +29,23 @@ export class GestureHandlerArkUIAdapter {
|
|
28
29
|
}
|
29
30
|
|
30
31
|
handleTouch(e: TouchEvent) {
|
32
|
+
const logger = this.logger.cloneAndJoinPrefix("handleTouch")
|
31
33
|
for (const changedTouch of e.changedTouches) {
|
32
|
-
if (this.shouldSkipTouch(changedTouch))
|
33
|
-
|
34
|
+
if (this.shouldSkipTouch(changedTouch)) {
|
35
|
+
continue;
|
36
|
+
}
|
37
|
+
const wasInBounds = this.pointerIdsInBounds.has(changedTouch.id);
|
34
38
|
const isInBounds = this.isInBounds({
|
35
39
|
x: changedTouch.windowX,
|
36
40
|
y: changedTouch.windowY,
|
37
41
|
});
|
38
|
-
|
39
|
-
|
42
|
+
logger.debug(
|
43
|
+
{
|
44
|
+
viewTag: this.view.getTag(),
|
40
45
|
type: changedTouch.type,
|
41
46
|
wasInBounds,
|
42
47
|
isInBounds,
|
43
|
-
}
|
48
|
+
},
|
44
49
|
);
|
45
50
|
const adaptedEvent = this.adaptTouchEvent(e, changedTouch);
|
46
51
|
this.gestureHandlers.forEach(gh => {
|
@@ -58,9 +63,11 @@ export class GestureHandlerArkUIAdapter {
|
|
58
63
|
gh.onAdditionalPointerRemove(adaptedEvent);
|
59
64
|
break;
|
60
65
|
case EventType.MOVE:
|
61
|
-
if (!wasInBounds && !isInBounds)
|
66
|
+
if (!wasInBounds && !isInBounds) {
|
62
67
|
gh.onPointerOutOfBounds(adaptedEvent);
|
63
|
-
else
|
68
|
+
} else {
|
69
|
+
gh.onPointerMove(adaptedEvent);
|
70
|
+
}
|
64
71
|
break;
|
65
72
|
case EventType.ENTER:
|
66
73
|
gh.onPointerEnter(adaptedEvent);
|
@@ -97,9 +104,10 @@ export class GestureHandlerArkUIAdapter {
|
|
97
104
|
changedTouch.type,
|
98
105
|
this.isInBounds({ x: xAbsolute, y: yAbsolute }),
|
99
106
|
changedTouch.id,
|
100
|
-
this.
|
107
|
+
this.pointerIdsInBounds.has(changedTouch.id),
|
101
108
|
);
|
102
|
-
this.logger.
|
109
|
+
this.logger.cloneAndJoinPrefix("adaptTouchEvent")
|
110
|
+
.debug({ eventType, activePointersCount: this.activePointerIds.size })
|
103
111
|
this.updateIsInBoundsByPointerId(
|
104
112
|
changedTouch.type,
|
105
113
|
changedTouch.id,
|
@@ -133,17 +141,25 @@ export class GestureHandlerArkUIAdapter {
|
|
133
141
|
) {
|
134
142
|
switch (touchType) {
|
135
143
|
case TouchType.Down:
|
136
|
-
if (this.isInBounds({ x, y }))
|
144
|
+
if (this.isInBounds({ x, y })) {
|
145
|
+
this.pointerIdsInBounds.add(pointerId);
|
146
|
+
}
|
137
147
|
break;
|
138
148
|
case TouchType.Move:
|
139
|
-
if (this.isInBounds({
|
140
|
-
|
149
|
+
if (this.isInBounds({
|
150
|
+
x,
|
151
|
+
y
|
152
|
+
})) {
|
153
|
+
this.pointerIdsInBounds.add(pointerId);
|
154
|
+
} else {
|
155
|
+
this.pointerIdsInBounds.delete(pointerId);
|
156
|
+
}
|
141
157
|
break;
|
142
158
|
case TouchType.Up:
|
143
|
-
this.
|
159
|
+
this.pointerIdsInBounds.delete(pointerId);
|
144
160
|
break;
|
145
161
|
case TouchType.Cancel:
|
146
|
-
this.
|
162
|
+
this.pointerIdsInBounds.delete(pointerId);
|
147
163
|
break;
|
148
164
|
}
|
149
165
|
}
|
@@ -152,7 +168,7 @@ export class GestureHandlerArkUIAdapter {
|
|
152
168
|
const x = point.x;
|
153
169
|
const y = point.y;
|
154
170
|
const rect = this.view.getBoundingRect();
|
155
|
-
this.logger.
|
171
|
+
this.logger.cloneAndJoinPrefix("isInBounds").debug({ rect })
|
156
172
|
const result =
|
157
173
|
x >= rect.x &&
|
158
174
|
x <= rect.x + rect.width &&
|
@@ -204,11 +220,17 @@ export class GestureHandlerArkUIAdapter {
|
|
204
220
|
|
205
221
|
switch (touchType) {
|
206
222
|
case TouchType.Down:
|
207
|
-
if (activePointersCount > 0)
|
208
|
-
|
223
|
+
if (activePointersCount > 0) {
|
224
|
+
return EventType.ADDITIONAL_POINTER_DOWN;
|
225
|
+
} else {
|
226
|
+
return EventType.DOWN;
|
227
|
+
}
|
209
228
|
case TouchType.Up:
|
210
|
-
if (activePointersCount > 1)
|
211
|
-
|
229
|
+
if (activePointersCount > 1) {
|
230
|
+
return EventType.ADDITIONAL_POINTER_UP;
|
231
|
+
} else {
|
232
|
+
return EventType.UP;
|
233
|
+
}
|
212
234
|
case TouchType.Move:
|
213
235
|
if (isCurrentlyInBounds) {
|
214
236
|
return wasInBounds ? EventType.MOVE : EventType.ENTER;
|
@@ -0,0 +1,19 @@
|
|
1
|
+
import { Tag, } from '@rnoh/react-native-openharmony/ts';
|
2
|
+
import { View, ViewRegistry } from '../core';
|
3
|
+
|
4
|
+
|
5
|
+
export class RNGHViewRegistry implements ViewRegistry {
|
6
|
+
private viewByTag = new Map<Tag, View>()
|
7
|
+
|
8
|
+
save(view: View) {
|
9
|
+
this.viewByTag.set(view.getTag(), view)
|
10
|
+
}
|
11
|
+
|
12
|
+
deleteByTag(viewTag: Tag) {
|
13
|
+
this.viewByTag.delete(viewTag)
|
14
|
+
}
|
15
|
+
|
16
|
+
getViewByTag(viewTag: Tag) {
|
17
|
+
return this.viewByTag.get(viewTag);
|
18
|
+
}
|
19
|
+
}
|