Skip to main content

ohos_arkui_binding/api/
gesture.rs

1//! Module api::gesture wrappers and related types.
2
3use std::{
4    cell::{LazyCell, RefCell},
5    collections::HashMap,
6    ffi::CString,
7    os::raw::c_void,
8    ptr::NonNull,
9    rc::Rc,
10    sync::{Mutex, OnceLock},
11};
12
13use ohos_arkui_input_binding::sys::ArkUI_NodeHandle;
14use ohos_arkui_input_binding::ArkUIErrorCode;
15#[cfg(feature = "api-20")]
16use ohos_arkui_sys::OH_ArkUI_PreventGestureRecognizerBegin;
17use ohos_arkui_sys::{
18    ArkUI_GestureEvent, ArkUI_GestureEventActionTypeMask, ArkUI_GestureEventTargetInfo,
19    ArkUI_GestureInterruptInfo, ArkUI_GestureInterruptResult, ArkUI_GestureRecognizer,
20    ArkUI_GestureRecognizerHandle, ArkUI_GestureRecognizerHandleArray,
21    ArkUI_NativeAPIVariantKind_ARKUI_NATIVE_GESTURE, ArkUI_NativeGestureAPI_1,
22    ArkUI_ParallelInnerGestureEvent, OH_ArkUI_GestureEventTargetInfo_IsScrollBegin,
23    OH_ArkUI_GestureEventTargetInfo_IsScrollEnd, OH_ArkUI_GestureEvent_GetActionType,
24    OH_ArkUI_GestureEvent_GetNode, OH_ArkUI_GestureEvent_GetRawInputEvent,
25    OH_ArkUI_GestureInterruptInfo_GetGestureEvent, OH_ArkUI_GestureInterruptInfo_GetRecognizer,
26    OH_ArkUI_GestureInterruptInfo_GetSystemFlag,
27    OH_ArkUI_GestureInterruptInfo_GetSystemRecognizerType, OH_ArkUI_LongPress_GetRepeatCount,
28    OH_ArkUI_PanGesture_GetOffsetX, OH_ArkUI_PanGesture_GetOffsetY,
29    OH_ArkUI_PanGesture_GetVelocity, OH_ArkUI_PanGesture_GetVelocityX,
30    OH_ArkUI_PanGesture_GetVelocityY, OH_ArkUI_ParallelInnerGestureEvent_GetConflictRecognizers,
31    OH_ArkUI_ParallelInnerGestureEvent_GetCurrentRecognizer,
32    OH_ArkUI_ParallelInnerGestureEvent_GetUserData, OH_ArkUI_PinchGesture_GetCenterX,
33    OH_ArkUI_PinchGesture_GetCenterY, OH_ArkUI_PinchGesture_GetScale,
34    OH_ArkUI_QueryModuleInterfaceByName, OH_ArkUI_RotationGesture_GetAngle,
35    OH_ArkUI_SwipeGesture_GetAngle, OH_ArkUI_SwipeGesture_GetVelocity,
36};
37#[cfg(feature = "api-18")]
38use ohos_arkui_sys::{
39    ArkUI_NativeGestureAPI_2, OH_ArkUI_GestureInterrupter_GetUserData,
40    OH_ArkUI_GetGestureParam_DirectMask, OH_ArkUI_GetGestureParam_FingerCount,
41    OH_ArkUI_GetGestureParam_angle, OH_ArkUI_GetGestureParam_distance,
42    OH_ArkUI_GetGestureParam_distanceThreshold, OH_ArkUI_GetGestureParam_duration,
43    OH_ArkUI_GetGestureParam_limitFingerCount, OH_ArkUI_GetGestureParam_repeat,
44    OH_ArkUI_GetGestureParam_speed,
45};
46#[cfg(feature = "api-15")]
47use ohos_arkui_sys::{
48    ArkUI_TouchRecognizerHandle, ArkUI_TouchRecognizerHandleArray,
49    OH_ArkUI_GestureInterruptInfo_GetTouchRecognizers, OH_ArkUI_TouchRecognizer_CancelTouch,
50    OH_ArkUI_TouchRecognizer_GetNodeHandle,
51};
52#[cfg(feature = "api-22")]
53use ohos_arkui_sys::{
54    OH_ArkUI_LongPressGesture_GetAllowableMovement, OH_ArkUI_LongPressGesture_SetAllowableMovement,
55};
56#[cfg(feature = "api-19")]
57use ohos_arkui_sys::{
58    OH_ArkUI_PanGesture_GetDistanceByToolType, OH_ArkUI_PanGesture_SetDistanceMap,
59};
60
61use crate::{
62    check_arkui_status, ArkUIError, ArkUIResult, GestureData, GestureEventAction, GestureEventData,
63    GestureInterruptResult, GestureRecognizerState, GestureRecognizerType, InnerGestureData,
64    LongPressGestureData, PanGestureData, PinchGestureData, RotationGestureData, SwipeGestureData,
65};
66
67thread_local! {
68    /// ArkUINativeGestureAPI1 struct
69    /// Only can be used in main thread
70    pub(crate) static ARK_UI_NATIVE_GESTURE_API_1: LazyCell<ArkUINativeGestureAPI1> =
71    LazyCell::new(ArkUINativeGestureAPI1::new);
72
73    #[cfg(feature = "api-18")]
74    pub(crate) static ARK_UI_NATIVE_GESTURE_API_2: LazyCell<ArkUINativeGestureAPI2> =
75    LazyCell::new(ArkUINativeGestureAPI2::new);
76}
77
78struct InnerGestureParallelCallbackContext {
79    callback: Box<dyn Fn(ParallelInnerGestureEventRef) -> Option<GestureRecognizerRef>>,
80}
81
82struct GestureEventTargetCallbackContext {
83    callback: Box<dyn Fn(GestureEventRef)>,
84}
85
86struct GestureInterrupterCallbackContext {
87    callback: Box<dyn Fn(GestureInterruptInfoRef) -> GestureInterruptResult>,
88}
89
90#[cfg(feature = "api-20")]
91struct TouchTestDoneCallbackContext {
92    callback: Box<dyn Fn(GestureEventRef, Vec<GestureRecognizerRef>)>,
93}
94
95struct GestureDisposeNotifyCallbackContext {
96    callback: Box<dyn Fn()>,
97}
98
99type InnerGestureParallelCallbackMap = HashMap<usize, usize>;
100type GestureEventTargetCallbackMap = HashMap<usize, usize>;
101type GestureInterrupterCallbackMap = HashMap<usize, usize>;
102#[cfg(feature = "api-20")]
103type TouchTestDoneCallbackMap = HashMap<usize, usize>;
104type GestureDisposeNotifyCallbackMap = HashMap<usize, usize>;
105
106static INNER_GESTURE_PARALLEL_CALLBACK_CONTEXTS: OnceLock<Mutex<InnerGestureParallelCallbackMap>> =
107    OnceLock::new();
108static GESTURE_EVENT_TARGET_CALLBACK_CONTEXTS: OnceLock<Mutex<GestureEventTargetCallbackMap>> =
109    OnceLock::new();
110static GESTURE_INTERRUPTER_CALLBACK_CONTEXTS: OnceLock<Mutex<GestureInterrupterCallbackMap>> =
111    OnceLock::new();
112#[cfg(feature = "api-20")]
113static TOUCH_TEST_DONE_CALLBACK_CONTEXTS: OnceLock<Mutex<TouchTestDoneCallbackMap>> =
114    OnceLock::new();
115static GESTURE_DISPOSE_NOTIFY_CALLBACK_CONTEXTS: OnceLock<Mutex<GestureDisposeNotifyCallbackMap>> =
116    OnceLock::new();
117
118fn inner_gesture_parallel_callback_contexts() -> &'static Mutex<InnerGestureParallelCallbackMap> {
119    INNER_GESTURE_PARALLEL_CALLBACK_CONTEXTS.get_or_init(|| Mutex::new(HashMap::new()))
120}
121
122fn gesture_event_target_callback_contexts() -> &'static Mutex<GestureEventTargetCallbackMap> {
123    GESTURE_EVENT_TARGET_CALLBACK_CONTEXTS.get_or_init(|| Mutex::new(HashMap::new()))
124}
125
126fn gesture_interrupter_callback_contexts() -> &'static Mutex<GestureInterrupterCallbackMap> {
127    GESTURE_INTERRUPTER_CALLBACK_CONTEXTS.get_or_init(|| Mutex::new(HashMap::new()))
128}
129
130#[cfg(feature = "api-20")]
131fn touch_test_done_callback_contexts() -> &'static Mutex<TouchTestDoneCallbackMap> {
132    TOUCH_TEST_DONE_CALLBACK_CONTEXTS.get_or_init(|| Mutex::new(HashMap::new()))
133}
134
135fn gesture_dispose_notify_callback_contexts() -> &'static Mutex<GestureDisposeNotifyCallbackMap> {
136    GESTURE_DISPOSE_NOTIFY_CALLBACK_CONTEXTS.get_or_init(|| Mutex::new(HashMap::new()))
137}
138
139pub(crate) struct ArkUINativeGestureAPI1(pub(crate) NonNull<ArkUI_NativeGestureAPI_1>);
140
141impl ArkUINativeGestureAPI1 {
142    /// allow us to get the pointer of ArkUI_NativeGestureAPI_1 and use it directly
143    pub(crate) fn raw(&self) -> *mut ArkUI_NativeGestureAPI_1 {
144        self.0.as_ptr()
145    }
146
147    pub fn new() -> Self {
148        let struct_name = CString::new("ArkUI_NativeGestureAPI_1").unwrap();
149        let raw_ptr = unsafe {
150            OH_ArkUI_QueryModuleInterfaceByName(
151                ArkUI_NativeAPIVariantKind_ARKUI_NATIVE_GESTURE,
152                struct_name.as_ptr().cast(),
153            )
154        };
155        let api = NonNull::new(raw_ptr.cast())
156            .unwrap_or_else(|| panic!("ArkUI_NativeGestureAPI_1 is NULL"));
157        Self(api)
158    }
159
160    pub fn create_long_gesture(
161        &self,
162        finger_number: i32,
163        repeat: bool,
164        duration: i32,
165    ) -> ArkUIResult<ArkUI_GestureRecognizerHandle> {
166        unsafe {
167            if let Some(create_long_press_gesture) = (*self.raw()).createLongPressGesture {
168                let ret = create_long_press_gesture(finger_number, repeat, duration);
169                if ret.is_null() {
170                    Err(ArkUIError::new(
171                        ArkUIErrorCode::AttributeOrEventNotSupported,
172                        "ArkUINativeGestureAPI1::createLongPressGesture is None",
173                    ))
174                } else {
175                    Ok(ret)
176                }
177            } else {
178                Err(ArkUIError::new(
179                    ArkUIErrorCode::AttributeOrEventNotSupported,
180                    "ArkUINativeGestureAPI1::createLongPressGesture is None",
181                ))
182            }
183        }
184    }
185
186    pub fn create_tap_gesture(
187        &self,
188        count: i32,
189        finger: i32,
190    ) -> ArkUIResult<ArkUI_GestureRecognizerHandle> {
191        unsafe {
192            if let Some(create_tap_gesture) = (*self.raw()).createTapGesture {
193                let ret = create_tap_gesture(count, finger);
194                if ret.is_null() {
195                    Err(ArkUIError::new(
196                        ArkUIErrorCode::AttributeOrEventNotSupported,
197                        "ArkUINativeGestureAPI1::createTapGesture is None",
198                    ))
199                } else {
200                    Ok(ret)
201                }
202            } else {
203                Err(ArkUIError::new(
204                    ArkUIErrorCode::AttributeOrEventNotSupported,
205                    "ArkUINativeGestureAPI1::createTapGesture is None",
206                ))
207            }
208        }
209    }
210
211    pub fn create_tap_gesture_with_distance_threshold(
212        &self,
213        count: i32,
214        finger: i32,
215        distance_threshold: f64,
216    ) -> ArkUIResult<ArkUI_GestureRecognizerHandle> {
217        unsafe {
218            if let Some(create_tap_gesture) = (*self.raw()).createTapGestureWithDistanceThreshold {
219                let ret = create_tap_gesture(count, finger, distance_threshold);
220                if ret.is_null() {
221                    Err(ArkUIError::new(
222                        ArkUIErrorCode::AttributeOrEventNotSupported,
223                        "ArkUINativeGestureAPI1::createTapGestureWithDistanceThreshold is None",
224                    ))
225                } else {
226                    Ok(ret)
227                }
228            } else {
229                Err(ArkUIError::new(
230                    ArkUIErrorCode::AttributeOrEventNotSupported,
231                    "ArkUINativeGestureAPI1::createTapGestureWithDistanceThreshold is None",
232                ))
233            }
234        }
235    }
236
237    pub fn create_pan_gesture(
238        &self,
239        finger: i32,
240        direction: crate::GestureDirection,
241        distance: f64,
242    ) -> ArkUIResult<ArkUI_GestureRecognizerHandle> {
243        unsafe {
244            if let Some(create_pan_gesture) = (*self.raw()).createPanGesture {
245                let ret = create_pan_gesture(finger, direction.into(), distance);
246                if ret.is_null() {
247                    Err(ArkUIError::new(
248                        ArkUIErrorCode::AttributeOrEventNotSupported,
249                        "ArkUINativeGestureAPI1::createPanGesture is None",
250                    ))
251                } else {
252                    Ok(ret)
253                }
254            } else {
255                Err(ArkUIError::new(
256                    ArkUIErrorCode::AttributeOrEventNotSupported,
257                    "ArkUINativeGestureAPI1::createPanGesture is None",
258                ))
259            }
260        }
261    }
262
263    pub fn create_pinch_gesture(
264        &self,
265        finger: i32,
266        distance: f64,
267    ) -> ArkUIResult<ArkUI_GestureRecognizerHandle> {
268        unsafe {
269            if let Some(create_pinch_gesture) = (*self.raw()).createPinchGesture {
270                let ret = create_pinch_gesture(finger, distance);
271                if ret.is_null() {
272                    Err(ArkUIError::new(
273                        ArkUIErrorCode::AttributeOrEventNotSupported,
274                        "ArkUINativeGestureAPI1::createPinchGesture is None",
275                    ))
276                } else {
277                    Ok(ret)
278                }
279            } else {
280                Err(ArkUIError::new(
281                    ArkUIErrorCode::AttributeOrEventNotSupported,
282                    "ArkUINativeGestureAPI1::createPinchGesture is None",
283                ))
284            }
285        }
286    }
287
288    pub fn create_rotation_gesture(
289        &self,
290        finger: i32,
291        angle: f64,
292    ) -> ArkUIResult<ArkUI_GestureRecognizerHandle> {
293        unsafe {
294            if let Some(create_rotation_gesture) = (*self.raw()).createRotationGesture {
295                let ret = create_rotation_gesture(finger, angle);
296                if ret.is_null() {
297                    Err(ArkUIError::new(
298                        ArkUIErrorCode::AttributeOrEventNotSupported,
299                        "ArkUINativeGestureAPI1::createRotationGesture is None",
300                    ))
301                } else {
302                    Ok(ret)
303                }
304            } else {
305                Err(ArkUIError::new(
306                    ArkUIErrorCode::AttributeOrEventNotSupported,
307                    "ArkUINativeGestureAPI1::createRotationGesture is None",
308                ))
309            }
310        }
311    }
312
313    pub fn create_swipe_gesture(
314        &self,
315        finger: i32,
316        direction: crate::GestureDirection,
317        speed: f64,
318    ) -> ArkUIResult<ArkUI_GestureRecognizerHandle> {
319        unsafe {
320            if let Some(create_swipe_gesture) = (*self.raw()).createSwipeGesture {
321                let ret = create_swipe_gesture(finger, direction.into(), speed);
322                if ret.is_null() {
323                    Err(ArkUIError::new(
324                        ArkUIErrorCode::AttributeOrEventNotSupported,
325                        "ArkUINativeGestureAPI1::createSwipeGesture is None",
326                    ))
327                } else {
328                    Ok(ret)
329                }
330            } else {
331                Err(ArkUIError::new(
332                    ArkUIErrorCode::AttributeOrEventNotSupported,
333                    "ArkUINativeGestureAPI1::createSwipeGesture is None",
334                ))
335            }
336        }
337    }
338
339    pub fn create_gesture_group(
340        &self,
341        mode: crate::GestureGroupMode,
342    ) -> ArkUIResult<ArkUI_GestureRecognizerHandle> {
343        unsafe {
344            if let Some(create_group_gesture) = (*self.raw()).createGroupGesture {
345                let ret = create_group_gesture(mode.into());
346                if ret.is_null() {
347                    Err(ArkUIError::new(
348                        ArkUIErrorCode::AttributeOrEventNotSupported,
349                        "ArkUINativeGestureAPI1::createGroupGesture is None",
350                    ))
351                } else {
352                    Ok(ret)
353                }
354            } else {
355                Err(ArkUIError::new(
356                    ArkUIErrorCode::AttributeOrEventNotSupported,
357                    "ArkUINativeGestureAPI1::createGestureGroup is None",
358                ))
359            }
360        }
361    }
362
363    pub fn add_child_gesture(
364        &self,
365        group: ArkUI_GestureRecognizerHandle,
366        child: ArkUI_GestureRecognizerHandle,
367    ) -> ArkUIResult<()> {
368        unsafe {
369            if let Some(add_child_gesture) = (*self.raw()).addChildGesture {
370                check_arkui_status!(add_child_gesture(group, child))
371            } else {
372                Err(ArkUIError::new(
373                    ArkUIErrorCode::AttributeOrEventNotSupported,
374                    "ArkUINativeGestureAPI1::addChildGesture is None",
375                ))
376            }
377        }
378    }
379
380    pub fn remove_child_gesture(
381        &self,
382        group: ArkUI_GestureRecognizerHandle,
383        child: ArkUI_GestureRecognizerHandle,
384    ) -> ArkUIResult<()> {
385        unsafe {
386            if let Some(remove_child_gesture) = (*self.raw()).removeChildGesture {
387                check_arkui_status!(remove_child_gesture(group, child))
388            } else {
389                Err(ArkUIError::new(
390                    ArkUIErrorCode::AttributeOrEventNotSupported,
391                    "ArkUINativeGestureAPI1::removeChildGesture is None",
392                ))
393            }
394        }
395    }
396
397    pub fn add_gesture(
398        &self,
399        gesture: ArkUI_GestureRecognizerHandle,
400        node: ArkUI_NodeHandle,
401        mode: crate::GesturePriority,
402        mask: crate::GestureMask,
403    ) -> ArkUIResult<()> {
404        unsafe {
405            if let Some(add_gesture_to_node) = (*self.raw()).addGestureToNode {
406                check_arkui_status!(add_gesture_to_node(node, gesture, mode.into(), mask.into()))
407            } else {
408                Err(ArkUIError::new(
409                    ArkUIErrorCode::AttributeOrEventNotSupported,
410                    "ArkUINativeGestureAPI1::addGestureToNode is None",
411                ))
412            }
413        }
414    }
415
416    pub fn remove_gesture(
417        &self,
418        gesture: ArkUI_GestureRecognizerHandle,
419        node: ArkUI_NodeHandle,
420    ) -> ArkUIResult<()> {
421        unsafe {
422            if let Some(remove_gesture_from_node) = (*self.raw()).removeGestureFromNode {
423                check_arkui_status!(remove_gesture_from_node(node, gesture))
424            } else {
425                Err(ArkUIError::new(
426                    ArkUIErrorCode::AttributeOrEventNotSupported,
427                    "ArkUINativeGestureAPI1::removeGestureFromNode is None",
428                ))
429            }
430        }
431    }
432
433    pub(crate) fn dispose_gesture(
434        &self,
435        gesture: ArkUI_GestureRecognizerHandle,
436    ) -> ArkUIResult<()> {
437        unsafe {
438            if let Some(dispose) = (*self.raw()).dispose {
439                dispose(gesture);
440                Ok(())
441            } else {
442                Err(ArkUIError::new(
443                    ArkUIErrorCode::AttributeOrEventNotSupported,
444                    "ArkUINativeGestureAPI1::dispose is None",
445                ))
446            }
447        }
448    }
449
450    pub fn get_gesture_type(
451        &self,
452        gesture: ArkUI_GestureRecognizerHandle,
453    ) -> ArkUIResult<GestureRecognizerType> {
454        unsafe {
455            if let Some(get_gesture_type) = (*self.raw()).getGestureType {
456                Ok(get_gesture_type(gesture).into())
457            } else {
458                Err(ArkUIError::new(
459                    ArkUIErrorCode::AttributeOrEventNotSupported,
460                    "ArkUINativeGestureAPI1::getGestureType is None",
461                ))
462            }
463        }
464    }
465
466    fn set_gesture_interrupter_to_node_raw(
467        &self,
468        node: ArkUI_NodeHandle,
469        interrupter: Option<
470            unsafe extern "C" fn(
471                info: *mut ArkUI_GestureInterruptInfo,
472            ) -> ArkUI_GestureInterruptResult,
473        >,
474    ) -> ArkUIResult<()> {
475        unsafe {
476            if let Some(set_gesture_interrupter_to_node) = (*self.raw()).setGestureInterrupterToNode
477            {
478                check_arkui_status!(set_gesture_interrupter_to_node(node, interrupter))
479            } else {
480                Err(ArkUIError::new(
481                    ArkUIErrorCode::AttributeOrEventNotSupported,
482                    "ArkUINativeGestureAPI1::setGestureInterrupterToNode is None",
483                ))
484            }
485        }
486    }
487
488    pub fn set_gesture_interrupter_to_node<
489        T: Fn(GestureInterruptInfoRef) -> GestureInterruptResult + 'static,
490    >(
491        &self,
492        node: ArkUI_NodeHandle,
493        interrupter: T,
494    ) -> ArkUIResult<()> {
495        let callback = Box::into_raw(Box::new(GestureInterrupterCallbackContext {
496            callback: Box::new(interrupter),
497        }));
498        let result = self.set_gesture_interrupter_to_node_raw(
499            node,
500            Some(gesture_interrupter_callback_trampoline),
501        );
502        if let Err(err) = result {
503            unsafe {
504                drop(Box::from_raw(callback));
505            }
506            return Err(err);
507        }
508        let mut callbacks = match gesture_interrupter_callback_contexts().lock() {
509            Ok(callbacks) => callbacks,
510            Err(poisoned) => poisoned.into_inner(),
511        };
512        if let Some(old) = callbacks.insert(node as usize, callback as usize) {
513            unsafe {
514                drop(Box::from_raw(old as *mut GestureInterrupterCallbackContext));
515            }
516        }
517        Ok(())
518    }
519
520    pub(crate) fn clear_gesture_interrupter_to_node(
521        &self,
522        node: ArkUI_NodeHandle,
523    ) -> ArkUIResult<()> {
524        self.set_gesture_interrupter_to_node_raw(node, None)?;
525        let mut callbacks = match gesture_interrupter_callback_contexts().lock() {
526            Ok(callbacks) => callbacks,
527            Err(poisoned) => poisoned.into_inner(),
528        };
529        if let Some(callback) = callbacks.remove(&(node as usize)) {
530            unsafe {
531                drop(Box::from_raw(
532                    callback as *mut GestureInterrupterCallbackContext,
533                ));
534            }
535        }
536        Ok(())
537    }
538
539    fn set_inner_gesture_parallel_to_raw(
540        &self,
541        node: ArkUI_NodeHandle,
542        user_data: *mut c_void,
543        parallel_inner_gesture: Option<
544            unsafe extern "C" fn(
545                event: *mut ArkUI_ParallelInnerGestureEvent,
546            ) -> *mut ArkUI_GestureRecognizer,
547        >,
548    ) -> ArkUIResult<()> {
549        unsafe {
550            if let Some(set_inner_gesture_parallel_to) = (*self.raw()).setInnerGestureParallelTo {
551                check_arkui_status!(set_inner_gesture_parallel_to(
552                    node,
553                    user_data,
554                    parallel_inner_gesture
555                ))
556            } else {
557                Err(ArkUIError::new(
558                    ArkUIErrorCode::AttributeOrEventNotSupported,
559                    "ArkUINativeGestureAPI1::setInnerGestureParallelTo is None",
560                ))
561            }
562        }
563    }
564
565    pub fn set_inner_gesture_parallel_to<
566        T: Fn(ParallelInnerGestureEventRef) -> Option<GestureRecognizerRef> + 'static,
567    >(
568        &self,
569        node: ArkUI_NodeHandle,
570        parallel_inner_gesture: T,
571    ) -> ArkUIResult<()> {
572        let callback = Box::into_raw(Box::new(InnerGestureParallelCallbackContext {
573            callback: Box::new(parallel_inner_gesture),
574        }));
575        let result = self.set_inner_gesture_parallel_to_raw(
576            node,
577            callback.cast(),
578            Some(inner_gesture_parallel_callback_trampoline),
579        );
580        if let Err(err) = result {
581            unsafe {
582                drop(Box::from_raw(callback));
583            }
584            return Err(err);
585        }
586        let mut callbacks = match inner_gesture_parallel_callback_contexts().lock() {
587            Ok(callbacks) => callbacks,
588            Err(poisoned) => poisoned.into_inner(),
589        };
590        if let Some(old) = callbacks.insert(node as usize, callback as usize) {
591            unsafe {
592                drop(Box::from_raw(
593                    old as *mut InnerGestureParallelCallbackContext,
594                ));
595            }
596        }
597        Ok(())
598    }
599
600    pub(crate) fn clear_inner_gesture_parallel_to(
601        &self,
602        node: ArkUI_NodeHandle,
603    ) -> ArkUIResult<()> {
604        self.set_inner_gesture_parallel_to_raw(node, std::ptr::null_mut(), None)?;
605        let mut callbacks = match inner_gesture_parallel_callback_contexts().lock() {
606            Ok(callbacks) => callbacks,
607            Err(poisoned) => poisoned.into_inner(),
608        };
609        if let Some(callback) = callbacks.remove(&(node as usize)) {
610            unsafe {
611                drop(Box::from_raw(
612                    callback as *mut InnerGestureParallelCallbackContext,
613                ));
614            }
615        }
616        Ok(())
617    }
618
619    #[cfg(feature = "api-20")]
620    pub fn prevent_gesture_recognizer_begin(
621        &self,
622        recognizer: ArkUI_GestureRecognizerHandle,
623    ) -> ArkUIResult<()> {
624        unsafe { check_arkui_status!(OH_ArkUI_PreventGestureRecognizerBegin(recognizer)) }
625    }
626
627    pub(crate) fn set_gesture_event_to_target(
628        &self,
629        gesture: ArkUI_GestureRecognizerHandle,
630        action_type: ArkUI_GestureEventActionTypeMask,
631        extra_params: Rc<RefCell<InnerGestureData>>,
632    ) -> ArkUIResult<()> {
633        self.set_gesture_event_target_raw(
634            gesture,
635            action_type,
636            Box::into_raw(Box::new(extra_params)) as *mut c_void,
637            Some(target_receiver),
638        )
639    }
640
641    fn set_gesture_event_target_raw(
642        &self,
643        gesture: ArkUI_GestureRecognizerHandle,
644        action_type: ArkUI_GestureEventActionTypeMask,
645        extra_params: *mut c_void,
646        target_receiver: Option<
647            unsafe extern "C" fn(event: *mut ArkUI_GestureEvent, extra_params: *mut c_void),
648        >,
649    ) -> ArkUIResult<()> {
650        unsafe {
651            if let Some(set_gesture_event_to_target) = (*self.raw()).setGestureEventTarget {
652                check_arkui_status!(set_gesture_event_to_target(
653                    gesture,
654                    action_type,
655                    extra_params,
656                    target_receiver
657                ))
658            } else {
659                Err(ArkUIError::new(
660                    ArkUIErrorCode::AttributeOrEventNotSupported,
661                    "ArkUINativeGestureAPI1::setGestureEventTarget is None",
662                ))
663            }
664        }
665    }
666
667    pub(crate) fn set_gesture_event_target<T: Fn(GestureEventRef) + 'static>(
668        &self,
669        gesture: ArkUI_GestureRecognizerHandle,
670        action_type: ArkUI_GestureEventActionTypeMask,
671        target_receiver: T,
672    ) -> ArkUIResult<()> {
673        let callback = Box::into_raw(Box::new(GestureEventTargetCallbackContext {
674            callback: Box::new(target_receiver),
675        }));
676        let result = self.set_gesture_event_target_raw(
677            gesture,
678            action_type,
679            callback.cast(),
680            Some(gesture_event_target_callback_trampoline),
681        );
682        if let Err(err) = result {
683            unsafe {
684                drop(Box::from_raw(callback));
685            }
686            return Err(err);
687        }
688        let mut callbacks = match gesture_event_target_callback_contexts().lock() {
689            Ok(callbacks) => callbacks,
690            Err(poisoned) => poisoned.into_inner(),
691        };
692        if let Some(old) = callbacks.insert(gesture as usize, callback as usize) {
693            unsafe {
694                drop(Box::from_raw(old as *mut GestureEventTargetCallbackContext));
695            }
696        }
697        Ok(())
698    }
699
700    pub fn clear_gesture_event_target(
701        &self,
702        gesture: ArkUI_GestureRecognizerHandle,
703        action_type: ArkUI_GestureEventActionTypeMask,
704    ) -> ArkUIResult<()> {
705        self.set_gesture_event_target_raw(gesture, action_type, std::ptr::null_mut(), None)?;
706        let mut callbacks = match gesture_event_target_callback_contexts().lock() {
707            Ok(callbacks) => callbacks,
708            Err(poisoned) => poisoned.into_inner(),
709        };
710        if let Some(callback) = callbacks.remove(&(gesture as usize)) {
711            unsafe {
712                drop(Box::from_raw(
713                    callback as *mut GestureEventTargetCallbackContext,
714                ));
715            }
716        }
717        Ok(())
718    }
719}
720
721impl Default for ArkUINativeGestureAPI1 {
722    fn default() -> Self {
723        Self::new()
724    }
725}
726
727#[cfg(feature = "api-18")]
728pub(crate) struct ArkUINativeGestureAPI2(pub(crate) NonNull<ArkUI_NativeGestureAPI_2>);
729
730#[cfg(feature = "api-18")]
731impl ArkUINativeGestureAPI2 {
732    pub(crate) fn raw(&self) -> *mut ArkUI_NativeGestureAPI_2 {
733        self.0.as_ptr()
734    }
735
736    pub fn new() -> Self {
737        let struct_name = CString::new("ArkUI_NativeGestureAPI_2").unwrap();
738        let raw_ptr = unsafe {
739            OH_ArkUI_QueryModuleInterfaceByName(
740                ArkUI_NativeAPIVariantKind_ARKUI_NATIVE_GESTURE,
741                struct_name.as_ptr().cast(),
742            )
743        };
744        let api = NonNull::new(raw_ptr.cast())
745            .unwrap_or_else(|| panic!("ArkUI_NativeGestureAPI_2 is NULL"));
746        Self(api)
747    }
748
749    fn set_gesture_interrupter_to_node_raw(
750        &self,
751        node: ArkUI_NodeHandle,
752        user_data: *mut c_void,
753        interrupter: Option<
754            unsafe extern "C" fn(
755                info: *mut ArkUI_GestureInterruptInfo,
756            ) -> ArkUI_GestureInterruptResult,
757        >,
758    ) -> ArkUIResult<()> {
759        unsafe {
760            if let Some(set_gesture_interrupter_to_node) = (*self.raw()).setGestureInterrupterToNode
761            {
762                check_arkui_status!(set_gesture_interrupter_to_node(
763                    node,
764                    user_data,
765                    interrupter
766                ))
767            } else {
768                Err(ArkUIError::new(
769                    ArkUIErrorCode::AttributeOrEventNotSupported,
770                    "ArkUINativeGestureAPI2::setGestureInterrupterToNode is None",
771                ))
772            }
773        }
774    }
775
776    pub fn set_gesture_interrupter_to_node<
777        T: Fn(GestureInterruptInfoRef) -> GestureInterruptResult + 'static,
778    >(
779        &self,
780        node: ArkUI_NodeHandle,
781        interrupter: T,
782    ) -> ArkUIResult<()> {
783        let callback = Box::into_raw(Box::new(GestureInterrupterCallbackContext {
784            callback: Box::new(interrupter),
785        }));
786        let result = self.set_gesture_interrupter_to_node_raw(
787            node,
788            callback.cast(),
789            Some(gesture_interrupter_callback_trampoline),
790        );
791        if let Err(err) = result {
792            unsafe {
793                drop(Box::from_raw(callback));
794            }
795            return Err(err);
796        }
797        let mut callbacks = match gesture_interrupter_callback_contexts().lock() {
798            Ok(callbacks) => callbacks,
799            Err(poisoned) => poisoned.into_inner(),
800        };
801        if let Some(old) = callbacks.insert(node as usize, callback as usize) {
802            unsafe {
803                drop(Box::from_raw(old as *mut GestureInterrupterCallbackContext));
804            }
805        }
806        Ok(())
807    }
808
809    pub(crate) fn clear_gesture_interrupter_to_node(
810        &self,
811        node: ArkUI_NodeHandle,
812    ) -> ArkUIResult<()> {
813        self.set_gesture_interrupter_to_node_raw(node, std::ptr::null_mut(), None)?;
814        let mut callbacks = match gesture_interrupter_callback_contexts().lock() {
815            Ok(callbacks) => callbacks,
816            Err(poisoned) => poisoned.into_inner(),
817        };
818        if let Some(callback) = callbacks.remove(&(node as usize)) {
819            unsafe {
820                drop(Box::from_raw(
821                    callback as *mut GestureInterrupterCallbackContext,
822                ));
823            }
824        }
825        Ok(())
826    }
827}
828
829#[cfg(feature = "api-18")]
830impl Default for ArkUINativeGestureAPI2 {
831    fn default() -> Self {
832        Self::new()
833    }
834}
835
836fn read_buffer_string<F>(mut reader: F) -> ArkUIResult<String>
837where
838    F: FnMut(*mut std::os::raw::c_char, i32, *mut i32) -> i32,
839{
840    let mut write_length = 0;
841    let mut buffer = vec![0u8; 256];
842    let mut status = reader(
843        buffer.as_mut_ptr().cast(),
844        buffer.len() as i32,
845        &mut write_length,
846    );
847    if write_length > buffer.len() as i32 {
848        buffer.resize(write_length as usize, 0);
849        status = reader(
850            buffer.as_mut_ptr().cast(),
851            buffer.len() as i32,
852            &mut write_length,
853        );
854    }
855    check_arkui_status!(status)?;
856    let mut end = (write_length as usize).min(buffer.len());
857    if end == 0 {
858        end = buffer.iter().position(|v| *v == 0).unwrap_or(0);
859    } else if buffer.get(end.saturating_sub(1)).copied() == Some(0) {
860        end -= 1;
861    }
862    Ok(String::from_utf8_lossy(&buffer[..end]).into_owned())
863}
864
865fn collect_gesture_recognizers(
866    recognizers: ArkUI_GestureRecognizerHandleArray,
867    count: i32,
868) -> Vec<GestureRecognizerRef> {
869    if recognizers.is_null() || count <= 0 {
870        return Vec::new();
871    }
872    let handles = unsafe { std::slice::from_raw_parts(recognizers, count as usize) };
873    handles
874        .iter()
875        .filter_map(|handle| GestureRecognizerRef::from_handle(*handle))
876        .collect()
877}
878
879#[derive(Clone, Copy, Debug)]
880/// Borrowed wrapper around `ArkUI_GestureEvent`.
881pub struct GestureEventRef {
882    raw: NonNull<ArkUI_GestureEvent>,
883}
884
885impl GestureEventRef {
886    pub(crate) fn from_raw(raw: *mut ArkUI_GestureEvent) -> Option<Self> {
887        NonNull::new(raw).map(|raw| Self { raw })
888    }
889
890    pub(crate) fn from_const_raw(raw: *const ArkUI_GestureEvent) -> Option<Self> {
891        Self::from_raw(raw.cast_mut())
892    }
893
894    fn raw(&self) -> *mut ArkUI_GestureEvent {
895        self.raw.as_ptr()
896    }
897
898    pub fn raw_input_event(&self) -> Option<ohos_arkui_input_binding::ArkUIInputEvent> {
899        let raw_input_event = unsafe { OH_ArkUI_GestureEvent_GetRawInputEvent(self.raw()) };
900        if raw_input_event.is_null() {
901            None
902        } else {
903            Some(ohos_arkui_input_binding::ArkUIInputEvent::from_raw(
904                raw_input_event.cast_mut(),
905            ))
906        }
907    }
908
909    pub fn node(&self) -> Option<crate::ArkUINode> {
910        let node = unsafe { OH_ArkUI_GestureEvent_GetNode(self.raw()) };
911        crate::ArkUINode::from_raw_handle(node)
912    }
913}
914
915#[derive(Clone, Copy, Debug)]
916/// Borrowed wrapper around `ArkUI_GestureEventTargetInfo`.
917pub struct GestureEventTargetInfoRef {
918    raw: NonNull<ArkUI_GestureEventTargetInfo>,
919}
920
921impl GestureEventTargetInfoRef {
922    fn from_raw(raw: *mut ArkUI_GestureEventTargetInfo) -> Option<Self> {
923        NonNull::new(raw).map(|raw| Self { raw })
924    }
925
926    fn raw(&self) -> *mut ArkUI_GestureEventTargetInfo {
927        self.raw.as_ptr()
928    }
929
930    pub fn is_scroll_begin(&self) -> ArkUIResult<bool> {
931        let mut ret = false;
932        check_arkui_status!(unsafe {
933            OH_ArkUI_GestureEventTargetInfo_IsScrollBegin(self.raw(), &mut ret)
934        })?;
935        Ok(ret)
936    }
937
938    pub fn is_scroll_end(&self) -> ArkUIResult<bool> {
939        let mut ret = false;
940        check_arkui_status!(unsafe {
941            OH_ArkUI_GestureEventTargetInfo_IsScrollEnd(self.raw(), &mut ret)
942        })?;
943        Ok(ret)
944    }
945}
946
947#[derive(Clone, Copy, Debug)]
948/// Borrowed wrapper around `ArkUI_GestureRecognizer`.
949pub struct GestureRecognizerRef {
950    raw: NonNull<ArkUI_GestureRecognizer>,
951}
952
953impl GestureRecognizerRef {
954    pub(crate) fn from_raw(raw: *mut ArkUI_GestureRecognizer) -> Option<Self> {
955        NonNull::new(raw).map(|raw| Self { raw })
956    }
957
958    pub(crate) fn from_handle(handle: ArkUI_GestureRecognizerHandle) -> Option<Self> {
959        Self::from_raw(handle)
960    }
961
962    pub(crate) fn raw(&self) -> *mut ArkUI_GestureRecognizer {
963        self.raw.as_ptr()
964    }
965
966    pub(crate) fn as_handle(&self) -> ArkUI_GestureRecognizerHandle {
967        self.raw()
968    }
969
970    pub fn set_enabled(&self, enabled: bool) -> ArkUIResult<()> {
971        unsafe {
972            check_arkui_status!(ohos_arkui_sys::OH_ArkUI_SetGestureRecognizerEnabled(
973                self.raw(),
974                enabled
975            ))
976        }
977    }
978
979    #[cfg(feature = "api-15")]
980    pub fn set_limit_finger_count(&self, limit_finger_count: bool) -> ArkUIResult<()> {
981        unsafe {
982            check_arkui_status!(
983                ohos_arkui_sys::OH_ArkUI_SetGestureRecognizerLimitFingerCount(
984                    self.raw(),
985                    limit_finger_count
986                )
987            )
988        }
989    }
990
991    pub fn enabled(&self) -> bool {
992        unsafe { ohos_arkui_sys::OH_ArkUI_GetGestureRecognizerEnabled(self.raw()) }
993    }
994
995    pub fn state(&self) -> ArkUIResult<GestureRecognizerState> {
996        let mut state =
997            ohos_arkui_sys::ArkUI_GestureRecognizerState_ARKUI_GESTURE_RECOGNIZER_STATE_READY;
998        unsafe {
999            check_arkui_status!(ohos_arkui_sys::OH_ArkUI_GetGestureRecognizerState(
1000                self.raw(),
1001                &mut state
1002            ))
1003        }?;
1004        Ok(state.into())
1005    }
1006
1007    pub fn event_target_info(&self) -> ArkUIResult<GestureEventTargetInfoRef> {
1008        let mut info = std::ptr::null_mut();
1009        unsafe {
1010            check_arkui_status!(ohos_arkui_sys::OH_ArkUI_GetGestureEventTargetInfo(
1011                self.raw(),
1012                &mut info
1013            ))
1014        }?;
1015        GestureEventTargetInfoRef::from_raw(info).ok_or_else(|| {
1016            ArkUIError::new(
1017                ArkUIErrorCode::ParamInvalid,
1018                "OH_ArkUI_GetGestureEventTargetInfo returned null",
1019            )
1020        })
1021    }
1022
1023    pub fn pan_direction_mask(&self) -> ArkUIResult<crate::GestureDirection> {
1024        let mut direction_mask: ohos_arkui_sys::ArkUI_GestureDirectionMask = 0;
1025        unsafe {
1026            check_arkui_status!(ohos_arkui_sys::OH_ArkUI_GetPanGestureDirectionMask(
1027                self.raw(),
1028                &mut direction_mask
1029            ))
1030        }?;
1031        Ok(direction_mask.into())
1032    }
1033
1034    pub fn is_built_in(&self) -> bool {
1035        unsafe { ohos_arkui_sys::OH_ArkUI_IsBuiltInGesture(self.raw()) }
1036    }
1037
1038    pub fn tag(&self) -> ArkUIResult<String> {
1039        read_buffer_string(|buffer, buffer_size, write_length| unsafe {
1040            ohos_arkui_sys::OH_ArkUI_GetGestureTag(self.raw(), buffer, buffer_size, write_length)
1041        })
1042    }
1043
1044    pub fn bind_node_id(&self) -> ArkUIResult<String> {
1045        read_buffer_string(|buffer, buffer_size, write_length| unsafe {
1046            ohos_arkui_sys::OH_ArkUI_GetGestureBindNodeId(
1047                self.raw(),
1048                buffer,
1049                buffer_size,
1050                write_length,
1051            )
1052        })
1053    }
1054
1055    pub fn is_valid(&self) -> bool {
1056        unsafe { ohos_arkui_sys::OH_ArkUI_IsGestureRecognizerValid(self.raw()) }
1057    }
1058
1059    pub fn set_dispose_notify<T: Fn() + 'static>(&self, callback: T) -> ArkUIResult<()> {
1060        let callback = Box::into_raw(Box::new(GestureDisposeNotifyCallbackContext {
1061            callback: Box::new(callback),
1062        }));
1063        let result = unsafe {
1064            check_arkui_status!(
1065                ohos_arkui_sys::OH_ArkUI_SetArkUIGestureRecognizerDisposeNotify(
1066                    self.raw(),
1067                    Some(gesture_dispose_notify_callback_trampoline),
1068                    callback.cast(),
1069                )
1070            )
1071        };
1072        if let Err(err) = result {
1073            unsafe {
1074                drop(Box::from_raw(callback));
1075            }
1076            return Err(err);
1077        }
1078        let mut callbacks = match gesture_dispose_notify_callback_contexts().lock() {
1079            Ok(callbacks) => callbacks,
1080            Err(poisoned) => poisoned.into_inner(),
1081        };
1082        if let Some(old) = callbacks.insert(self.as_handle() as usize, callback as usize) {
1083            unsafe {
1084                drop(Box::from_raw(
1085                    old as *mut GestureDisposeNotifyCallbackContext,
1086                ));
1087            }
1088        }
1089        Ok(())
1090    }
1091
1092    pub fn clear_dispose_notify(&self) -> ArkUIResult<()> {
1093        unsafe {
1094            check_arkui_status!(
1095                ohos_arkui_sys::OH_ArkUI_SetArkUIGestureRecognizerDisposeNotify(
1096                    self.raw(),
1097                    None,
1098                    std::ptr::null_mut(),
1099                )
1100            )
1101        }?;
1102        let mut callbacks = match gesture_dispose_notify_callback_contexts().lock() {
1103            Ok(callbacks) => callbacks,
1104            Err(poisoned) => poisoned.into_inner(),
1105        };
1106        if let Some(callback) = callbacks.remove(&(self.as_handle() as usize)) {
1107            unsafe {
1108                drop(Box::from_raw(
1109                    callback as *mut GestureDisposeNotifyCallbackContext,
1110                ));
1111            }
1112        }
1113        Ok(())
1114    }
1115
1116    #[cfg(feature = "api-19")]
1117    pub fn set_distance_map(
1118        &self,
1119        tool_type_array: &mut [i32],
1120        distance_array: &mut [f64],
1121    ) -> ArkUIResult<()> {
1122        if tool_type_array.len() != distance_array.len() {
1123            return Err(ArkUIError::new(
1124                ArkUIErrorCode::ParamInvalid,
1125                "tool_type_array and distance_array must have the same length",
1126            ));
1127        }
1128        check_arkui_status!(unsafe {
1129            OH_ArkUI_PanGesture_SetDistanceMap(
1130                self.as_handle(),
1131                tool_type_array.len() as i32,
1132                tool_type_array.as_mut_ptr(),
1133                distance_array.as_mut_ptr(),
1134            )
1135        })
1136    }
1137
1138    #[cfg(feature = "api-19")]
1139    pub fn distance_by_tool_type(&self, tool_type: i32) -> ArkUIResult<f64> {
1140        let mut distance = 0f64;
1141        check_arkui_status!(unsafe {
1142            OH_ArkUI_PanGesture_GetDistanceByToolType(self.as_handle(), tool_type, &mut distance)
1143        })?;
1144        Ok(distance)
1145    }
1146
1147    #[cfg(feature = "api-18")]
1148    pub fn param_direct_mask(&self) -> ArkUIResult<crate::GestureDirection> {
1149        let mut direction_mask = 0;
1150        check_arkui_status!(unsafe {
1151            OH_ArkUI_GetGestureParam_DirectMask(self.as_handle(), &mut direction_mask)
1152        })?;
1153        Ok(direction_mask.into())
1154    }
1155
1156    #[cfg(feature = "api-18")]
1157    pub fn param_finger_count(&self) -> ArkUIResult<i32> {
1158        let mut finger = 0;
1159        check_arkui_status!(unsafe {
1160            OH_ArkUI_GetGestureParam_FingerCount(self.as_handle(), &mut finger)
1161        })?;
1162        Ok(finger)
1163    }
1164
1165    #[cfg(feature = "api-18")]
1166    pub fn param_limit_finger_count(&self) -> ArkUIResult<bool> {
1167        let mut limited = false;
1168        check_arkui_status!(unsafe {
1169            OH_ArkUI_GetGestureParam_limitFingerCount(self.as_handle(), &mut limited)
1170        })?;
1171        Ok(limited)
1172    }
1173
1174    #[cfg(feature = "api-18")]
1175    pub fn param_repeat(&self) -> ArkUIResult<bool> {
1176        let mut repeat = false;
1177        check_arkui_status!(unsafe {
1178            OH_ArkUI_GetGestureParam_repeat(self.as_handle(), &mut repeat)
1179        })?;
1180        Ok(repeat)
1181    }
1182
1183    #[cfg(feature = "api-18")]
1184    pub fn param_distance(&self) -> ArkUIResult<f64> {
1185        let mut distance = 0f64;
1186        check_arkui_status!(unsafe {
1187            OH_ArkUI_GetGestureParam_distance(self.as_handle(), &mut distance)
1188        })?;
1189        Ok(distance)
1190    }
1191
1192    #[cfg(feature = "api-18")]
1193    pub fn param_speed(&self) -> ArkUIResult<f64> {
1194        let mut speed = 0f64;
1195        check_arkui_status!(unsafe {
1196            OH_ArkUI_GetGestureParam_speed(self.as_handle(), &mut speed)
1197        })?;
1198        Ok(speed)
1199    }
1200
1201    #[cfg(feature = "api-18")]
1202    pub fn param_duration(&self) -> ArkUIResult<i32> {
1203        let mut duration = 0;
1204        check_arkui_status!(unsafe {
1205            OH_ArkUI_GetGestureParam_duration(self.as_handle(), &mut duration)
1206        })?;
1207        Ok(duration)
1208    }
1209
1210    #[cfg(feature = "api-18")]
1211    pub fn param_angle(&self) -> ArkUIResult<f64> {
1212        let mut angle = 0f64;
1213        check_arkui_status!(unsafe {
1214            OH_ArkUI_GetGestureParam_angle(self.as_handle(), &mut angle)
1215        })?;
1216        Ok(angle)
1217    }
1218
1219    #[cfg(feature = "api-18")]
1220    pub fn param_distance_threshold(&self) -> ArkUIResult<f64> {
1221        let mut distance_threshold = 0f64;
1222        check_arkui_status!(unsafe {
1223            OH_ArkUI_GetGestureParam_distanceThreshold(self.as_handle(), &mut distance_threshold)
1224        })?;
1225        Ok(distance_threshold)
1226    }
1227
1228    #[cfg(feature = "api-22")]
1229    pub fn set_allowable_movement(&self, allowable_movement: f64) -> ArkUIResult<()> {
1230        check_arkui_status!(unsafe {
1231            OH_ArkUI_LongPressGesture_SetAllowableMovement(self.as_handle(), allowable_movement)
1232        })
1233    }
1234
1235    #[cfg(feature = "api-22")]
1236    pub fn allowable_movement(&self) -> ArkUIResult<f64> {
1237        let mut allowable_movement = 0f64;
1238        check_arkui_status!(unsafe {
1239            OH_ArkUI_LongPressGesture_GetAllowableMovement(
1240                self.as_handle(),
1241                &mut allowable_movement,
1242            )
1243        })?;
1244        Ok(allowable_movement)
1245    }
1246}
1247
1248#[derive(Clone, Copy, Debug)]
1249/// Borrowed wrapper around `ArkUI_GestureInterruptInfo`.
1250pub struct GestureInterruptInfoRef {
1251    raw: NonNull<ArkUI_GestureInterruptInfo>,
1252}
1253
1254impl GestureInterruptInfoRef {
1255    pub(crate) fn from_raw(raw: *mut ArkUI_GestureInterruptInfo) -> Option<Self> {
1256        NonNull::new(raw).map(|raw| Self { raw })
1257    }
1258
1259    pub(crate) fn from_const_raw(raw: *const ArkUI_GestureInterruptInfo) -> Option<Self> {
1260        Self::from_raw(raw.cast_mut())
1261    }
1262
1263    fn raw(&self) -> *mut ArkUI_GestureInterruptInfo {
1264        self.raw.as_ptr()
1265    }
1266
1267    pub fn system_flag(&self) -> bool {
1268        unsafe { OH_ArkUI_GestureInterruptInfo_GetSystemFlag(self.raw()) }
1269    }
1270
1271    pub fn recognizer(&self) -> Option<GestureRecognizerRef> {
1272        let recognizer = unsafe { OH_ArkUI_GestureInterruptInfo_GetRecognizer(self.raw()) };
1273        GestureRecognizerRef::from_raw(recognizer)
1274    }
1275
1276    pub fn gesture_event(&self) -> Option<GestureEventRef> {
1277        let gesture_event = unsafe { OH_ArkUI_GestureInterruptInfo_GetGestureEvent(self.raw()) };
1278        GestureEventRef::from_raw(gesture_event)
1279    }
1280
1281    pub fn system_recognizer_type(&self) -> Option<crate::GestureRecognizerType> {
1282        let recognizer_type =
1283            unsafe { OH_ArkUI_GestureInterruptInfo_GetSystemRecognizerType(self.raw()) };
1284        if recognizer_type < 0 {
1285            None
1286        } else {
1287            crate::GestureRecognizerType::try_from_raw(
1288                recognizer_type as ohos_arkui_sys::ArkUI_GestureRecognizerType,
1289            )
1290        }
1291    }
1292
1293    pub fn response_recognizers(&self) -> ArkUIResult<Vec<GestureRecognizerRef>> {
1294        let mut response_chain: ArkUI_GestureRecognizerHandleArray = std::ptr::null_mut();
1295        let mut count = 0;
1296        unsafe {
1297            check_arkui_status!(
1298                ohos_arkui_sys::OH_ArkUI_GetResponseRecognizersFromInterruptInfo(
1299                    self.raw(),
1300                    &mut response_chain,
1301                    &mut count
1302                )
1303            )
1304        }?;
1305        Ok(collect_gesture_recognizers(response_chain, count))
1306    }
1307
1308    #[cfg(feature = "api-15")]
1309    pub fn touch_recognizers(&self) -> ArkUIResult<Vec<TouchRecognizerRef>> {
1310        let mut recognizers: ArkUI_TouchRecognizerHandleArray = std::ptr::null_mut();
1311        let mut size = 0;
1312        check_arkui_status!(unsafe {
1313            OH_ArkUI_GestureInterruptInfo_GetTouchRecognizers(
1314                self.raw(),
1315                &mut recognizers,
1316                &mut size,
1317            )
1318        })?;
1319        if recognizers.is_null() || size <= 0 {
1320            return Ok(Vec::new());
1321        }
1322        let handles = unsafe { std::slice::from_raw_parts(recognizers, size as usize) };
1323        Ok(handles
1324            .iter()
1325            .filter_map(|handle| TouchRecognizerRef::from_handle(*handle))
1326            .collect())
1327    }
1328}
1329
1330#[cfg(feature = "api-15")]
1331#[derive(Clone, Copy, Debug)]
1332/// Borrowed wrapper around `ArkUI_TouchRecognizerHandle`.
1333pub struct TouchRecognizerRef {
1334    raw: NonNull<c_void>,
1335}
1336
1337#[cfg(feature = "api-15")]
1338impl TouchRecognizerRef {
1339    pub(crate) fn from_handle(handle: ArkUI_TouchRecognizerHandle) -> Option<Self> {
1340        NonNull::new(handle.cast()).map(|raw| Self { raw })
1341    }
1342
1343    fn raw(&self) -> ArkUI_TouchRecognizerHandle {
1344        self.raw.as_ptr().cast()
1345    }
1346
1347    pub fn node(&self) -> Option<crate::ArkUINode> {
1348        let node = unsafe { OH_ArkUI_TouchRecognizer_GetNodeHandle(self.raw()) };
1349        crate::ArkUINode::from_raw_handle(node)
1350    }
1351
1352    pub fn cancel_touch(&self, info: GestureInterruptInfoRef) -> ArkUIResult<()> {
1353        check_arkui_status!(unsafe { OH_ArkUI_TouchRecognizer_CancelTouch(self.raw(), info.raw()) })
1354    }
1355}
1356
1357#[derive(Clone, Copy, Debug)]
1358/// Borrowed wrapper around `ArkUI_ParallelInnerGestureEvent`.
1359pub struct ParallelInnerGestureEventRef {
1360    raw: NonNull<ArkUI_ParallelInnerGestureEvent>,
1361}
1362
1363impl ParallelInnerGestureEventRef {
1364    pub(crate) fn from_raw(raw: *mut ArkUI_ParallelInnerGestureEvent) -> Option<Self> {
1365        NonNull::new(raw).map(|raw| Self { raw })
1366    }
1367
1368    fn raw(&self) -> *mut ArkUI_ParallelInnerGestureEvent {
1369        self.raw.as_ptr()
1370    }
1371
1372    pub fn user_data(&self) -> Option<NonNull<c_void>> {
1373        NonNull::new(unsafe { OH_ArkUI_ParallelInnerGestureEvent_GetUserData(self.raw()) })
1374    }
1375
1376    pub fn current_recognizer(&self) -> Option<GestureRecognizerRef> {
1377        let recognizer =
1378            unsafe { OH_ArkUI_ParallelInnerGestureEvent_GetCurrentRecognizer(self.raw()) };
1379        GestureRecognizerRef::from_raw(recognizer)
1380    }
1381
1382    pub fn conflict_recognizers(&self) -> ArkUIResult<Vec<GestureRecognizerRef>> {
1383        let mut array: ArkUI_GestureRecognizerHandleArray = std::ptr::null_mut();
1384        let mut size = 0;
1385        check_arkui_status!(unsafe {
1386            OH_ArkUI_ParallelInnerGestureEvent_GetConflictRecognizers(
1387                self.raw(),
1388                &mut array,
1389                &mut size,
1390            )
1391        })?;
1392        Ok(collect_gesture_recognizers(array, size))
1393    }
1394}
1395
1396#[cfg(feature = "api-20")]
1397fn set_touch_test_done_callback_raw(
1398    node: &crate::ArkUINode,
1399    user_data: *mut c_void,
1400    touch_test_done: Option<
1401        unsafe extern "C" fn(
1402            event: *mut ArkUI_GestureEvent,
1403            recognizers: ArkUI_GestureRecognizerHandleArray,
1404            count: i32,
1405            user_data: *mut c_void,
1406        ),
1407    >,
1408) -> ArkUIResult<()> {
1409    unsafe {
1410        check_arkui_status!(ohos_arkui_sys::OH_ArkUI_SetTouchTestDoneCallback(
1411            node.raw(),
1412            user_data,
1413            touch_test_done
1414        ))
1415    }
1416}
1417
1418impl crate::ArkUIHandle {
1419    #[cfg(feature = "api-20")]
1420    pub fn set_touch_test_done_callback<
1421        T: Fn(GestureEventRef, Vec<GestureRecognizerRef>) + 'static,
1422    >(
1423        &self,
1424        node: &crate::ArkUINode,
1425        touch_test_done: T,
1426    ) -> ArkUIResult<()> {
1427        let _ = self.raw();
1428        let callback = Box::into_raw(Box::new(TouchTestDoneCallbackContext {
1429            callback: Box::new(touch_test_done),
1430        }));
1431        let result = set_touch_test_done_callback_raw(
1432            node,
1433            callback.cast(),
1434            Some(touch_test_done_callback_trampoline),
1435        );
1436        if let Err(err) = result {
1437            unsafe {
1438                drop(Box::from_raw(callback));
1439            }
1440            return Err(err);
1441        }
1442        let mut callbacks = match touch_test_done_callback_contexts().lock() {
1443            Ok(callbacks) => callbacks,
1444            Err(poisoned) => poisoned.into_inner(),
1445        };
1446        if let Some(old) = callbacks.insert(node.raw() as usize, callback as usize) {
1447            unsafe {
1448                drop(Box::from_raw(old as *mut TouchTestDoneCallbackContext));
1449            }
1450        }
1451        Ok(())
1452    }
1453
1454    #[cfg(feature = "api-20")]
1455    pub(crate) fn clear_touch_test_done_callback(
1456        &self,
1457        node: &crate::ArkUINode,
1458    ) -> ArkUIResult<()> {
1459        let _ = self.raw();
1460        set_touch_test_done_callback_raw(node, std::ptr::null_mut(), None)?;
1461        let mut callbacks = match touch_test_done_callback_contexts().lock() {
1462            Ok(callbacks) => callbacks,
1463            Err(poisoned) => poisoned.into_inner(),
1464        };
1465        if let Some(callback) = callbacks.remove(&(node.raw() as usize)) {
1466            unsafe {
1467                drop(Box::from_raw(callback as *mut TouchTestDoneCallbackContext));
1468            }
1469        }
1470        Ok(())
1471    }
1472}
1473
1474unsafe extern "C" fn inner_gesture_parallel_callback_trampoline(
1475    event: *mut ArkUI_ParallelInnerGestureEvent,
1476) -> *mut ArkUI_GestureRecognizer {
1477    let Some(event) = ParallelInnerGestureEventRef::from_raw(event) else {
1478        return std::ptr::null_mut();
1479    };
1480    let user_data = unsafe { OH_ArkUI_ParallelInnerGestureEvent_GetUserData(event.raw()) };
1481    if user_data.is_null() {
1482        return std::ptr::null_mut();
1483    }
1484    let callback = unsafe { &*(user_data as *mut InnerGestureParallelCallbackContext) };
1485    match (callback.callback)(event) {
1486        Some(recognizer) => recognizer.as_handle(),
1487        None => std::ptr::null_mut(),
1488    }
1489}
1490
1491unsafe extern "C" fn gesture_event_target_callback_trampoline(
1492    event: *mut ArkUI_GestureEvent,
1493    extra_params: *mut c_void,
1494) {
1495    if extra_params.is_null() {
1496        return;
1497    }
1498    let Some(event) = GestureEventRef::from_raw(event) else {
1499        return;
1500    };
1501    let callback = unsafe { &*(extra_params as *mut GestureEventTargetCallbackContext) };
1502    (callback.callback)(event);
1503}
1504
1505unsafe extern "C" fn gesture_interrupter_callback_trampoline(
1506    info: *mut ArkUI_GestureInterruptInfo,
1507) -> ArkUI_GestureInterruptResult {
1508    let Some(info) = GestureInterruptInfoRef::from_raw(info) else {
1509        return GestureInterruptResult::Continue.into();
1510    };
1511
1512    #[cfg(feature = "api-18")]
1513    let user_data = unsafe { OH_ArkUI_GestureInterrupter_GetUserData(info.raw()) };
1514    #[cfg(feature = "api-18")]
1515    if !user_data.is_null() {
1516        let callback = unsafe { &*(user_data as *mut GestureInterrupterCallbackContext) };
1517        return (callback.callback)(info).into();
1518    }
1519
1520    let Some(node_handle) = info
1521        .gesture_event()
1522        .and_then(|event| event.node())
1523        .map(|node| node.raw())
1524    else {
1525        return GestureInterruptResult::Continue.into();
1526    };
1527
1528    let callback = {
1529        let callbacks = match gesture_interrupter_callback_contexts().lock() {
1530            Ok(callbacks) => callbacks,
1531            Err(poisoned) => poisoned.into_inner(),
1532        };
1533        callbacks.get(&(node_handle as usize)).copied()
1534    };
1535    let Some(callback) = callback else {
1536        return GestureInterruptResult::Continue.into();
1537    };
1538    let callback = unsafe { &*(callback as *const GestureInterrupterCallbackContext) };
1539    (callback.callback)(info).into()
1540}
1541
1542#[cfg(feature = "api-20")]
1543unsafe extern "C" fn touch_test_done_callback_trampoline(
1544    event: *mut ArkUI_GestureEvent,
1545    recognizers: ArkUI_GestureRecognizerHandleArray,
1546    count: i32,
1547    user_data: *mut c_void,
1548) {
1549    if user_data.is_null() {
1550        return;
1551    }
1552    let Some(event) = GestureEventRef::from_raw(event) else {
1553        return;
1554    };
1555    let callback = unsafe { &*(user_data as *mut TouchTestDoneCallbackContext) };
1556    (callback.callback)(event, collect_gesture_recognizers(recognizers, count));
1557}
1558
1559unsafe extern "C" fn gesture_dispose_notify_callback_trampoline(
1560    recognizer: *mut ArkUI_GestureRecognizer,
1561    user_data: *mut c_void,
1562) {
1563    if user_data.is_null() {
1564        return;
1565    }
1566    let callback = unsafe { Box::from_raw(user_data as *mut GestureDisposeNotifyCallbackContext) };
1567    (callback.callback)();
1568    let mut callbacks = match gesture_dispose_notify_callback_contexts().lock() {
1569        Ok(callbacks) => callbacks,
1570        Err(poisoned) => poisoned.into_inner(),
1571    };
1572    if !recognizer.is_null() {
1573        callbacks.remove(&(recognizer as usize));
1574    } else {
1575        callbacks.retain(|_, value| *value != user_data as usize);
1576    }
1577}
1578
1579unsafe extern "C" fn target_receiver(event: *mut ArkUI_GestureEvent, extra_params: *mut c_void) {
1580    let user_data: &Rc<RefCell<InnerGestureData>> =
1581        &*(extra_params as *const Rc<RefCell<InnerGestureData>>);
1582
1583    let data = user_data.borrow_mut();
1584    let event_action_type: GestureEventAction = OH_ArkUI_GestureEvent_GetActionType(event).into();
1585
1586    let event_data: GestureData = match data.gesture_type {
1587        GestureRecognizerType::LongPressGesture => {
1588            let repeat = OH_ArkUI_LongPress_GetRepeatCount(event);
1589            GestureData::LongPress(LongPressGestureData { repeat })
1590        }
1591        GestureRecognizerType::TapGesture => GestureData::Tap,
1592        GestureRecognizerType::PanGesture => {
1593            let velocity = OH_ArkUI_PanGesture_GetVelocity(event);
1594            let velocity_x = OH_ArkUI_PanGesture_GetVelocityX(event);
1595            let velocity_y = OH_ArkUI_PanGesture_GetVelocityY(event);
1596            let offset_x = OH_ArkUI_PanGesture_GetOffsetX(event);
1597            let offset_y = OH_ArkUI_PanGesture_GetOffsetY(event);
1598            GestureData::Pan(PanGestureData {
1599                velocity,
1600                velocity_x,
1601                velocity_y,
1602                offset_x,
1603                offset_y,
1604            })
1605        }
1606        GestureRecognizerType::PinchGesture => {
1607            let scale = OH_ArkUI_PinchGesture_GetScale(event);
1608            let center_x = OH_ArkUI_PinchGesture_GetCenterX(event);
1609            let center_y = OH_ArkUI_PinchGesture_GetCenterY(event);
1610            GestureData::Pinch(PinchGestureData {
1611                scale,
1612                center_x,
1613                center_y,
1614            })
1615        }
1616        GestureRecognizerType::RotationGesture => {
1617            let angle = OH_ArkUI_RotationGesture_GetAngle(event);
1618            GestureData::Rotation(RotationGestureData { angle })
1619        }
1620        GestureRecognizerType::SwipeGesture => {
1621            let angle = OH_ArkUI_SwipeGesture_GetAngle(event);
1622            let velocity = OH_ArkUI_SwipeGesture_GetVelocity(event);
1623            GestureData::Swipe(SwipeGestureData { angle, velocity })
1624        }
1625        _ => unreachable!("Invalid gesture type"),
1626    };
1627
1628    if let Some(event) = data.gesture_callback.as_ref() {
1629        event(GestureEventData {
1630            data: data.user_data,
1631            event_action_type,
1632            event_action_data: event_data,
1633        });
1634    }
1635}