diff --git a/build/libace.map b/build/libace.map index be46ec985958a1d22499105a3c4e776b109ecbd6..8e1314072188401f5bea356e7074f4a72c76310e 100644 --- a/build/libace.map +++ b/build/libace.map @@ -269,6 +269,7 @@ OHOS::Ace::PipelineBase::GetSystemFont*; OHOS::Ace::PipelineBase::GetUIFontConfig*; OHOS::Ace::PipelineBase::GetImageCache*; + OHOS::Ace::PipelineBase::ConvertPxToVp*; OHOS::Ace::ImageCache::ClearCacheImgObj*; OHOS::Ace::NG::ViewAbstract::*; OHOS::Ace::NG::Inspector::*; @@ -555,6 +556,9 @@ "OHOS::Ace::CheckThread(OHOS::Ace::TaskExecutor::TaskType)"; OHOS::Ace::NG::PanRecognizer::GetDistance*; OHOS::Ace::NG::NodeRenderStatusMonitor::*; + "OHOS::Ace::RoundToMaxPrecision(double)"; + OHOS::Ace::NG::SwiperPattern::IsAtStart*; + OHOS::Ace::NG::SwiperPattern::IsAtEnd*; }; local: *; diff --git a/frameworks/bridge/declarative_frontend/engine/jsUIContext.js b/frameworks/bridge/declarative_frontend/engine/jsUIContext.js index 7b8da97d298271bb7d0f239658edf1cf35b71e08..06ba04a9efb7c3230471db4cb8a87073aedd9d2f 100644 --- a/frameworks/bridge/declarative_frontend/engine/jsUIContext.js +++ b/frameworks/bridge/declarative_frontend/engine/jsUIContext.js @@ -226,6 +226,16 @@ class UIObserver { this.ohos_observer.off(...args); __JSScopeUtil__.restoreInstanceId(); } + addGlobalGestureListener(...args) { + __JSScopeUtil__.syncInstanceId(this.instanceId_); + this.ohos_observer?.addGlobalGestureListener(...args); + __JSScopeUtil__.restoreInstanceId(); + } + removeGlobalGestureListener(...args) { + __JSScopeUtil__.syncInstanceId(this.instanceId_); + this.ohos_observer?.removeGlobalGestureListener(...args); + __JSScopeUtil__.restoreInstanceId(); + } } class MeasureUtils { diff --git a/frameworks/core/components_ng/base/observer_handler.cpp b/frameworks/core/components_ng/base/observer_handler.cpp index 9606ab745580c050b65cf6e86feda8f35773e42e..83ec11882b6983f29bc536509c337b25311214e8 100644 --- a/frameworks/core/components_ng/base/observer_handler.cpp +++ b/frameworks/core/components_ng/base/observer_handler.cpp @@ -183,6 +183,17 @@ void UIObserverHandler::NotifyPanGestureStateChange(const GestureEvent& gestureE panGestureHandleFunc_(info, gestureEventInfo, current, frameNode, panGestureInfo); } +void UIObserverHandler::NotifyGestureStateChange(NG::GestureListenerType gestureListenerType, + const GestureEvent& gestureEventInfo, const RefPtr& current, + const RefPtr& frameNode, NG::GestureActionPhase phase) +{ + CHECK_NULL_VOID(current); + CHECK_NULL_VOID(frameNode); + CHECK_NULL_VOID(gestureHandleFunc_); + + gestureHandleFunc_(gestureListenerType, gestureEventInfo, current, frameNode, phase); +} + void UIObserverHandler::NotifyTabContentStateUpdate(const TabContentInfo& info) { CHECK_NULL_VOID(tabContentStateHandleFunc_); @@ -409,6 +420,11 @@ void UIObserverHandler::SetPanGestureHandleFunc(PanGestureHandleFunc func) panGestureHandleFunc_ = func; } +void UIObserverHandler::SetHandleGestureHandleFunc(GestureHandleFunc func) +{ + gestureHandleFunc_ = func; +} + void UIObserverHandler::SetHandleTabContentStateUpdateFunc(TabContentStateHandleFunc func) { tabContentStateHandleFunc_ = func; diff --git a/frameworks/core/components_ng/base/observer_handler.h b/frameworks/core/components_ng/base/observer_handler.h index fa8e8a6d17b16c129325da05212c366f479b70d2..6f8505f2451a22267ed9d4d69fd82c3606d7eb33 100644 --- a/frameworks/core/components_ng/base/observer_handler.h +++ b/frameworks/core/components_ng/base/observer_handler.h @@ -168,6 +168,10 @@ struct PanGestureInfo { CurrentCallbackState callbackState; }; +enum class GestureListenerType { TAP = 0, LONG_PRESS, PAN, PINCH, SWIPE, ROTATION, UNKNOWN }; + +enum class GestureActionPhase { WILL_START = 0, WILL_END = 1, UNKNOWN = 2 }; + class ACE_FORCE_EXPORT UIObserverHandler { public: UIObserverHandler() = default; @@ -185,6 +189,8 @@ public: const RefPtr& current, const RefPtr& frameNode, const PanGestureInfo& panGestureInfo); void NotifyTabContentStateUpdate(const TabContentInfo& info); + void NotifyGestureStateChange(NG::GestureListenerType gestureListenerType, const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr& frameNode, NG::GestureActionPhase phase); std::shared_ptr GetNavigationState(const RefPtr& node); std::shared_ptr GetNavDestinationInfo(const RefPtr& current); std::shared_ptr GetNavigationInnerState(const RefPtr& node); @@ -205,6 +211,9 @@ public: AbilityContextInfo&, const GestureEvent&, const ClickInfo&, const RefPtr&); using PanGestureHandleFunc = void (*)(AbilityContextInfo&, const GestureEvent&, const RefPtr& current, const RefPtr&, const NG::PanGestureInfo& panGestureInfo); + using GestureHandleFunc = void (*)(NG::GestureListenerType gestureListenerType, + const GestureEvent& gestureEventInfo, const RefPtr& current, + const RefPtr& frameNode, NG::GestureActionPhase phase); using TabContentStateHandleFunc = void (*)(const TabContentInfo&); NavDestinationSwitchHandleFunc GetHandleNavDestinationSwitchFunc(); void SetHandleNavigationChangeFunc(NavigationHandleFunc func); @@ -221,6 +230,7 @@ public: void SetDidClickFunc(DidClickHandleFunc func); void SetPanGestureHandleFunc(PanGestureHandleFunc func); void SetHandleTabContentStateUpdateFunc(TabContentStateHandleFunc func); + void SetHandleGestureHandleFunc(GestureHandleFunc func); private: NavigationHandleFunc navigationHandleFunc_ = nullptr; ScrollEventHandleFunc scrollEventHandleFunc_ = nullptr; @@ -233,6 +243,7 @@ private: DidClickHandleFunc didClickHandleFunc_ = nullptr; PanGestureHandleFunc panGestureHandleFunc_ = nullptr; TabContentStateHandleFunc tabContentStateHandleFunc_ = nullptr; + GestureHandleFunc gestureHandleFunc_ = nullptr; napi_value GetUIContextValue(); }; diff --git a/frameworks/core/components_ng/gestures/recognizers/click_recognizer.cpp b/frameworks/core/components_ng/gestures/recognizers/click_recognizer.cpp index 83267fa966917480082d5991df3f9abe14c556c3..da78c6fd64ca987df36caf4417973a9d5b52e76f 100644 --- a/frameworks/core/components_ng/gestures/recognizers/click_recognizer.cpp +++ b/frameworks/core/components_ng/gestures/recognizers/click_recognizer.cpp @@ -530,6 +530,7 @@ void ClickRecognizer::SendCallbackMsg(const std::unique_ptr& o info.SetGestureTypeName(GestureTypeName::TAP_GESTURE); // onAction may be overwritten in its invoke so we copy it first auto onActionFunction = *onAction; + HandleGestureAccept(info, type); onActionFunction(info); HandleReports(info, type); RecordClickEventIfNeed(info); diff --git a/frameworks/core/components_ng/gestures/recognizers/gesture_recognizer.cpp b/frameworks/core/components_ng/gestures/recognizers/gesture_recognizer.cpp index cae54d56631008026507af557e67c597d202cd71..906773ef03771816a7ff09a05448bdbb21cc4468 100644 --- a/frameworks/core/components_ng/gestures/recognizers/gesture_recognizer.cpp +++ b/frameworks/core/components_ng/gestures/recognizers/gesture_recognizer.cpp @@ -16,6 +16,7 @@ #include "core/components_ng/gestures/recognizers/gesture_recognizer.h" #include "core/components_ng/base/observer_handler.h" +#include "core/components_ng/gestures/recognizers/swipe_recognizer.h" #include "core/components_ng/manager/event/json_report.h" #include "core/components_ng/manager/drag_drop/drag_drop_behavior_reporter/drag_drop_behavior_reporter.h" @@ -696,4 +697,70 @@ std::string NGGestureRecognizer::GetCallbackName(const std::unique_ptrGetRecognizerType()); + if (listenerType == GestureListenerType::UNKNOWN) { + return; + } + GestureActionPhase phase = GetActionPhase(type, gestureInfo->GetRecognizerType()); + if (phase == GestureActionPhase::UNKNOWN) { + return; + } + UIObserverHandler::GetInstance().NotifyGestureStateChange(listenerType, info, Claim(this), node, phase); +} + +GestureListenerType NGGestureRecognizer::GetListenerType(GestureTypeName typeName) const +{ + switch (typeName) { + case GestureTypeName::PAN_GESTURE: + return GestureListenerType::PAN; + case GestureTypeName::PINCH_GESTURE: + return GestureListenerType::PINCH; + case GestureTypeName::ROTATION_GESTURE: + return GestureListenerType::ROTATION; + case GestureTypeName::TAP_GESTURE: + return GestureListenerType::TAP; + case GestureTypeName::SWIPE_GESTURE: + return GestureListenerType::SWIPE; + case GestureTypeName::LONG_PRESS_GESTURE: + return GestureListenerType::LONG_PRESS; + default: + return GestureListenerType::UNKNOWN; + } +} + +GestureActionPhase NGGestureRecognizer::GetActionPhase(GestureCallbackType callbackType, GestureTypeName typeName) const +{ + static const std::unordered_set startSupportedGestures = { + GestureTypeName::PAN_GESTURE, + GestureTypeName::PINCH_GESTURE, + GestureTypeName::ROTATION_GESTURE, + // LONG_PRESS_GESTURE when onAction, callbackType is START + GestureTypeName::LONG_PRESS_GESTURE + }; + + switch (callbackType) { + case GestureCallbackType::START: + return (startSupportedGestures.count(typeName)) ? GestureActionPhase::WILL_START + : GestureActionPhase::UNKNOWN; + + case GestureCallbackType::END: + return (startSupportedGestures.count(typeName)) ? GestureActionPhase::WILL_END + : GestureActionPhase::UNKNOWN; + + case GestureCallbackType::ACTION: + // ACTION will only be mapped to WILL_START if the START gesture is not supported + return (!startSupportedGestures.count(typeName)) ? GestureActionPhase::WILL_START + : GestureActionPhase::UNKNOWN; + + default: + return GestureActionPhase::UNKNOWN; + } +} } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/gestures/recognizers/gesture_recognizer.h b/frameworks/core/components_ng/gestures/recognizers/gesture_recognizer.h index bd43cdace5f286302045659e534fbf074908bd75..67e39fb8054bce225096680f9afb1c70152fe8db 100644 --- a/frameworks/core/components_ng/gestures/recognizers/gesture_recognizer.h +++ b/frameworks/core/components_ng/gestures/recognizers/gesture_recognizer.h @@ -27,6 +27,8 @@ #include "frameworks/base/geometry/ng/point_t.h" namespace OHOS::Ace::NG { +enum class GestureListenerType; +enum class GestureActionPhase; struct DelayedTask { WeakPtr recognizer; @@ -476,6 +478,7 @@ protected: void HandleTouchDown(const TouchEvent& point); void HandleTouchUp(const TouchEvent& point); void HandleTouchCancel(const TouchEvent& point); + void HandleGestureAccept(const GestureEvent& info, GestureCallbackType type); RefereeState refereeState_ = RefereeState::READY; @@ -524,6 +527,8 @@ protected: private: WeakPtr gestureGroup_; WeakPtr eventImportGestureGroup_; + GestureListenerType GetListenerType(GestureTypeName typeName) const; + GestureActionPhase GetActionPhase(GestureCallbackType callbackType, GestureTypeName typeName) const; }; } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/gestures/recognizers/long_press_recognizer.cpp b/frameworks/core/components_ng/gestures/recognizers/long_press_recognizer.cpp index e4e198a86616c900427cc46e9e0f7ca38573cc99..0bd4c67253aa7dd9414e8e43146ccae4869ced93 100644 --- a/frameworks/core/components_ng/gestures/recognizers/long_press_recognizer.cpp +++ b/frameworks/core/components_ng/gestures/recognizers/long_press_recognizer.cpp @@ -397,6 +397,12 @@ void LongPressRecognizer::SendCallbackMsg( if (type == GestureCallbackType::START) { isOnActionTriggered_ = true; } + TriggerCallbackMsg(callback, isRepeat, type); +} + +void LongPressRecognizer::TriggerCallbackMsg( + const std::unique_ptr& callback, bool isRepeat, GestureCallbackType type) +{ if (callback && *callback) { GestureEvent info; info.SetGestureTypeName(GestureTypeName::LONG_PRESS_GESTURE); @@ -429,6 +435,7 @@ void LongPressRecognizer::SendCallbackMsg( info.CopyConvertInfoFrom(lastTouchEvent_.convertInfo); // callback may be overwritten in its invoke so we copy it first auto callbackFunction = *callback; + HandleGestureAccept(info, type); callbackFunction(info); HandleReports(info, type); if (type == GestureCallbackType::START && longPressRecorder_ && *longPressRecorder_) { diff --git a/frameworks/core/components_ng/gestures/recognizers/long_press_recognizer.h b/frameworks/core/components_ng/gestures/recognizers/long_press_recognizer.h index 11793f350be73fad62c52d642bffba22ed02f8ff..6e057963d6e05a6eeb2447ba7649011440b0a28c 100644 --- a/frameworks/core/components_ng/gestures/recognizers/long_press_recognizer.h +++ b/frameworks/core/components_ng/gestures/recognizers/long_press_recognizer.h @@ -149,6 +149,7 @@ private: void ThumbnailTimer(int32_t time); RefPtr GetDragEventActuator(); OnAccessibilityEventFunc GetOnAccessibilityEventFunc(); + void TriggerCallbackMsg(const std::unique_ptr& callback, bool isRepeat, GestureCallbackType type); int32_t duration_ = 500; bool repeat_ = false; diff --git a/frameworks/core/components_ng/gestures/recognizers/pan_recognizer.cpp b/frameworks/core/components_ng/gestures/recognizers/pan_recognizer.cpp index 0d1641baebbee1e87e0218a0d307e0fd2756cba1..461007fc40e380fd3257015f046add891f98dc7b 100644 --- a/frameworks/core/components_ng/gestures/recognizers/pan_recognizer.cpp +++ b/frameworks/core/components_ng/gestures/recognizers/pan_recognizer.cpp @@ -820,11 +820,21 @@ void PanRecognizer::SendCallbackMsg(const std::unique_ptr& cal GestureEvent info = GetGestureEventInfo(); // callback may be overwritten in its invoke so we copy it first auto callbackFunction = *callback; - HandlePanGestureAccept(info, PanGestureState::BEFORE, callback); + HandleCallbackReports(info, type, PanGestureState::BEFORE); callbackFunction(info); + HandleCallbackReports(info, type, PanGestureState::AFTER); + } +} + +void PanRecognizer::HandleCallbackReports( + const GestureEvent& info, GestureCallbackType type, PanGestureState panGestureState) +{ + if (panGestureState == PanGestureState::BEFORE) { + HandleGestureAccept(info, type); + } else if (panGestureState == PanGestureState::AFTER) { HandleReports(info, type); - HandlePanGestureAccept(info, PanGestureState::AFTER, callback); } + HandlePanGestureAccept(info, panGestureState, type); } void PanRecognizer::HandleReports(const GestureEvent& info, GestureCallbackType type) @@ -1181,14 +1191,14 @@ void PanRecognizer::DumpVelocityInfo(int32_t fingerId) } void PanRecognizer::HandlePanGestureAccept( - const GestureEvent& info, PanGestureState panGestureState, const std::unique_ptr& callback) + const GestureEvent& info, PanGestureState panGestureState, GestureCallbackType type) { - if (callback == onActionStart_) { + if (type == GestureCallbackType::START) { currentCallbackState_ = CurrentCallbackState::START; auto node = GetAttachedNode().Upgrade(); UIObserverHandler::GetInstance().NotifyPanGestureStateChange( info, Claim(this), node, { panGestureState, currentCallbackState_ }); - } else if (callback == onActionEnd_) { + } else if (type == GestureCallbackType::END) { currentCallbackState_ = CurrentCallbackState::END; auto node = GetAttachedNode().Upgrade(); UIObserverHandler::GetInstance().NotifyPanGestureStateChange( diff --git a/frameworks/core/components_ng/gestures/recognizers/pan_recognizer.h b/frameworks/core/components_ng/gestures/recognizers/pan_recognizer.h index 7997f9416a2ffc04de25d16e295fe83571871a1f..2535ce3d9d73f76ddb6228cad91ce434fe4e3a87 100644 --- a/frameworks/core/components_ng/gestures/recognizers/pan_recognizer.h +++ b/frameworks/core/components_ng/gestures/recognizers/pan_recognizer.h @@ -90,14 +90,18 @@ public: return distanceMap_; } - void HandlePanGestureAccept( - const GestureEvent& info, PanGestureState panGestureState, const std::unique_ptr& callback); + void HandlePanGestureAccept(const GestureEvent& info, PanGestureState panGestureState, GestureCallbackType type); void SetPanEndCallback(const GestureEventFunc& panEndCallback) { panEndOnDisableState_ = std::make_unique(panEndCallback); } + const RefPtr& GetPanGestureOption() const + { + return panGestureOption_; + } + private: class PanVelocity { public: @@ -145,6 +149,7 @@ private: Offset GetRawGlobalLocation(int32_t postEventNodeId); void SendCallbackMsg(const std::unique_ptr& callback, GestureCallbackType type); + void HandleCallbackReports(const GestureEvent& info, GestureCallbackType type, PanGestureState panGestureState); void HandleReports(const GestureEvent& info, GestureCallbackType type) override; GestureJudgeResult TriggerGestureJudgeCallback(); void ChangeFingers(int32_t fingers); diff --git a/frameworks/core/components_ng/gestures/recognizers/pinch_recognizer.cpp b/frameworks/core/components_ng/gestures/recognizers/pinch_recognizer.cpp index 63b5ceee1a56afe79b6aa6a60f3ebb10592b0b26..f56521a95ba67854e6ecf82f8e2a9076d38e64d3 100644 --- a/frameworks/core/components_ng/gestures/recognizers/pinch_recognizer.cpp +++ b/frameworks/core/components_ng/gestures/recognizers/pinch_recognizer.cpp @@ -451,6 +451,7 @@ void PinchRecognizer::SendCallbackMsg(const std::unique_ptr& c info.SetInputEventType(inputEventType_); // callback may be overwritten in its invoke so we copy it first auto callbackFunction = *callback; + HandleGestureAccept(info, type); callbackFunction(info); HandleReports(info, type); } diff --git a/frameworks/core/components_ng/gestures/recognizers/rotation_recognizer.cpp b/frameworks/core/components_ng/gestures/recognizers/rotation_recognizer.cpp index 56bd78d7070cbd2a220561dca07819bc2002ff3b..d6dd67a2134ffafa9d065c5ae2f5dadccd2f927c 100644 --- a/frameworks/core/components_ng/gestures/recognizers/rotation_recognizer.cpp +++ b/frameworks/core/components_ng/gestures/recognizers/rotation_recognizer.cpp @@ -399,6 +399,7 @@ void RotationRecognizer::SendCallbackMsg(const std::unique_ptr info.SetInputEventType(inputEventType_); // callback may be overwritten in its invoke so we copy it first auto callbackFunction = *callback; + HandleGestureAccept(info, type); callbackFunction(info); HandleReports(info, type); } diff --git a/frameworks/core/components_ng/gestures/recognizers/swipe_recognizer.cpp b/frameworks/core/components_ng/gestures/recognizers/swipe_recognizer.cpp index aabfbf964381803473322be8c650c8567959672f..d6ec68fc597185fdfb882f49611e4ee77c3d03f0 100644 --- a/frameworks/core/components_ng/gestures/recognizers/swipe_recognizer.cpp +++ b/frameworks/core/components_ng/gestures/recognizers/swipe_recognizer.cpp @@ -434,6 +434,7 @@ void SwipeRecognizer::SendCallbackMsg(const std::unique_ptr& c info.SetInputEventType(inputEventType_); // callback may be overwritten in its invoke so we copy it first auto callbackFunction = *callback; + HandleGestureAccept(info, type); callbackFunction(info); HandleReports(info, type); } diff --git a/frameworks/core/components_ng/pattern/swiper/swiper_pattern.h b/frameworks/core/components_ng/pattern/swiper/swiper_pattern.h index 6f1287304421a0c60839ba541f255f1bc7bec1f3..cdfcd1d34e6a1e30baceb13696b5f29ee0141d87 100644 --- a/frameworks/core/components_ng/pattern/swiper/swiper_pattern.h +++ b/frameworks/core/components_ng/pattern/swiper/swiper_pattern.h @@ -648,8 +648,8 @@ public: isIndicatorInteractive_ = isInteractive; } - bool IsAtStart() const; - bool IsAtEnd() const; + ACE_FORCE_EXPORT bool IsAtStart() const; + ACE_FORCE_EXPORT bool IsAtEnd() const; bool IsIndicatorInteractive() const { diff --git a/interfaces/inner_api/ace_kit/include/ui/base/utils/utils.h b/interfaces/inner_api/ace_kit/include/ui/base/utils/utils.h index 498dde90d8b8554719060e995821afa41e08700c..5982d983cc02710aefcee7847229981c1ba8c3ee 100644 --- a/interfaces/inner_api/ace_kit/include/ui/base/utils/utils.h +++ b/interfaces/inner_api/ace_kit/include/ui/base/utils/utils.h @@ -21,6 +21,8 @@ #include #include +#include "ui/base/macros.h" + #define CHECK_NULL_VOID(ptr) \ do { \ if (!(ptr)) { \ @@ -320,7 +322,7 @@ inline bool IsDarkColor(uint32_t color) bool RealPath(const std::string& fileName, char* realPath); -double RoundToMaxPrecision(double value); +ACE_FORCE_EXPORT double RoundToMaxPrecision(double value); } // namespace OHOS::Ace diff --git a/interfaces/napi/kits/observer/BUILD.gn b/interfaces/napi/kits/observer/BUILD.gn index e0035ed3ec7b281897482be3a0d8d48902320e55..822971cbcd9e0f6d37e8d17d2d80bc69b5d44ba8 100644 --- a/interfaces/napi/kits/observer/BUILD.gn +++ b/interfaces/napi/kits/observer/BUILD.gn @@ -24,6 +24,8 @@ template("napi_observer_static") { configs = [ "$ace_root/interfaces/napi/kits:ace_napi_config" ] sources = [ + "gesture/gesture_observer.cpp", + "gesture/gesture_observer_listener.cpp", "js_ui_observer.cpp", "ui_observer.cpp", "ui_observer_listener.cpp", diff --git a/interfaces/napi/kits/observer/gesture/gesture_observer.cpp b/interfaces/napi/kits/observer/gesture/gesture_observer.cpp new file mode 100644 index 0000000000000000000000000000000000000000..39952e142f9d9ce3b0286aa0aaf9998d057ee92c --- /dev/null +++ b/interfaces/napi/kits/observer/gesture/gesture_observer.cpp @@ -0,0 +1,350 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gesture_observer.h" + +#include "gesture_observer_listener.h" +#include "interfaces/napi/kits/observer/ui_observer_listener.h" + +#include "bridge/common/utils/engine_helper.h" + +namespace OHOS::Ace::Napi { + +constexpr napi_status NAPI_ERR = napi_status::napi_generic_failure; +constexpr size_t ARG_COUNT_ONE = 1; +constexpr size_t ARG_COUNT_TWO = 2; +constexpr size_t ARG_COUNT_THREE = 3; + +constexpr uint32_t WILL_START = 0; +constexpr uint32_t WILL_END = 1; + +static constexpr size_t PARAM_INDEX_ZERO = 0; +static constexpr size_t PARAM_INDEX_ONE = 1; +static constexpr size_t PARAM_INDEX_TWO = 2; + +std::unordered_map>>> + GestureObserver::GestureObserverListeners_; +std::mutex GestureObserver::mutex_; + +bool GestureObserver::isGestureHandleFuncSetted_ = false; + +bool ParseGestureListenerType(napi_env env, napi_value value, NG::GestureListenerType& outType) +{ + if (!GestureObserverListener::MatchValueType(env, value, napi_number)) { + return false; + } + + uint32_t typeValue; + napi_get_value_uint32(env, value, &typeValue); + + switch (typeValue) { + case static_cast(NG::GestureListenerType::TAP): + case static_cast(NG::GestureListenerType::LONG_PRESS): + case static_cast(NG::GestureListenerType::PAN): + case static_cast(NG::GestureListenerType::PINCH): + case static_cast(NG::GestureListenerType::SWIPE): + case static_cast(NG::GestureListenerType::ROTATION): + outType = static_cast(typeValue); + return true; + default: + return false; + } +} + +bool ParseGestureActionPhase( + napi_env env, napi_value value, NG::GestureActionPhase& outPhase, NG::GestureListenerType gestureListenerType) +{ + if (!GestureObserverListener::MatchValueType(env, value, napi_number)) { + return false; + } + + uint32_t phaseValue; + napi_get_value_uint32(env, value, &phaseValue); + switch (phaseValue) { + case static_cast(NG::GestureActionPhase::WILL_START): + outPhase = static_cast(phaseValue); + return true; + case static_cast(NG::GestureActionPhase::WILL_END): + if (gestureListenerType == NG::GestureListenerType::TAP || + gestureListenerType == NG::GestureListenerType::SWIPE) { + return false; + } + outPhase = static_cast(phaseValue); + return true; + default: + return false; + } +} + +bool ParseActionPhasesArray(napi_env env, napi_value arrayValue, std::unordered_set& outPhases, + NG::GestureListenerType gestureListenerType) +{ + bool isArray; + napi_is_array(env, arrayValue, &isArray); + if (!isArray) { + return false; + } + + uint32_t arrayLength; + napi_get_array_length(env, arrayValue, &arrayLength); + for (uint32_t i = 0; i < arrayLength; ++i) { + napi_value element; + napi_get_element(env, arrayValue, i, &element); + + NG::GestureActionPhase phase; + if (!ParseGestureActionPhase(env, element, phase, gestureListenerType)) { + continue; + } + outPhases.insert(phase); + } + return !outPhases.empty(); +} + +bool ParseGestureObserverConfigs(napi_env env, napi_value configValue, + std::unordered_set& outPhase, NG::GestureListenerType gestureListenerType) +{ + napi_valuetype valueType; + napi_typeof(env, configValue, &valueType); + if (valueType != napi_object) { + return false; + } + + napi_value actionPhasesValue; + napi_status status = napi_get_named_property(env, configValue, "actionPhases", &actionPhasesValue); + if (status != napi_ok) { + return false; + } + + if (!ParseActionPhasesArray(env, actionPhasesValue, outPhase, gestureListenerType)) { + return false; + } + return true; +} + +napi_value AddGestureListenerType(napi_env env) +{ + napi_value gestureListenerType = nullptr; + napi_value prop = nullptr; + NAPI_CALL(env, napi_create_object(env, &gestureListenerType)); + NAPI_CALL(env, napi_create_uint32(env, static_cast(NG::GestureListenerType::TAP), &prop)); + NAPI_CALL(env, napi_set_named_property(env, gestureListenerType, "TAP", prop)); + NAPI_CALL(env, napi_create_uint32(env, static_cast(NG::GestureListenerType::LONG_PRESS), &prop)); + NAPI_CALL(env, napi_set_named_property(env, gestureListenerType, "LONG_PRESS", prop)); + NAPI_CALL(env, napi_create_uint32(env, static_cast(NG::GestureListenerType::PAN), &prop)); + NAPI_CALL(env, napi_set_named_property(env, gestureListenerType, "PAN", prop)); + NAPI_CALL(env, napi_create_uint32(env, static_cast(NG::GestureListenerType::PINCH), &prop)); + NAPI_CALL(env, napi_set_named_property(env, gestureListenerType, "PINCH", prop)); + NAPI_CALL(env, napi_create_uint32(env, static_cast(NG::GestureListenerType::SWIPE), &prop)); + NAPI_CALL(env, napi_set_named_property(env, gestureListenerType, "SWIPE", prop)); + NAPI_CALL(env, napi_create_uint32(env, static_cast(NG::GestureListenerType::ROTATION), &prop)); + NAPI_CALL(env, napi_set_named_property(env, gestureListenerType, "ROTATION", prop)); + return gestureListenerType; +} + +napi_value AddGestureActionPhase(napi_env env) +{ + napi_value gestureActionPhase = nullptr; + napi_value prop = nullptr; + NAPI_CALL(env, napi_create_object(env, &gestureActionPhase)); + NAPI_CALL(env, napi_create_uint32(env, WILL_START, &prop)); + NAPI_CALL(env, napi_set_named_property(env, gestureActionPhase, "WILL_START", prop)); + NAPI_CALL(env, napi_create_uint32(env, WILL_END, &prop)); + NAPI_CALL(env, napi_set_named_property(env, gestureActionPhase, "WILL_END", prop)); + return gestureActionPhase; +} + +napi_status GestureObserver::DefineGestureObserver(napi_env env, napi_value exports) +{ + napi_property_descriptor gestureObserverDesc[] = { + DECLARE_NAPI_FUNCTION("addGlobalGestureListener", AddGlobalGestureListener), + DECLARE_NAPI_FUNCTION("removeGlobalGestureListener", RemoveGlobalGestureListener), + DECLARE_NAPI_PROPERTY("GestureListenerType", AddGestureListenerType(env)), + DECLARE_NAPI_PROPERTY("GestureActionPhase", AddGestureActionPhase(env)), + }; + NAPI_CALL_BASE(env, + napi_define_properties( + env, exports, sizeof(gestureObserverDesc) / sizeof(gestureObserverDesc[0]), gestureObserverDesc), + NAPI_ERR); + return napi_ok; +} + +napi_value GestureObserver::AddGlobalGestureListener(napi_env env, napi_callback_info info) +{ + napi_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_handle_scope(env, &scope)); + size_t argc = ARG_COUNT_THREE; + napi_value argv[ARG_COUNT_THREE] = { nullptr }; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + if (argc != ARG_COUNT_THREE) { + napi_close_handle_scope(env, scope); + LOGE("Invalid arguments"); + return nullptr; + } + NG::GestureListenerType gestureListenerType; + if (!ParseGestureListenerType(env, argv[PARAM_INDEX_ZERO], gestureListenerType)) { + napi_close_handle_scope(env, scope); + return nullptr; + } + std::unordered_set outPhases; + if (!ParseGestureObserverConfigs(env, argv[PARAM_INDEX_ONE], outPhases, gestureListenerType)) { + napi_close_handle_scope(env, scope); + return nullptr; + } + + if (!isGestureHandleFuncSetted_) { + NG::UIObserverHandler::GetInstance().SetHandleGestureHandleFunc(&HandleGestureAccept); + isGestureHandleFuncSetted_ = true; + } + + auto listener = std::make_shared(env, argv[PARAM_INDEX_TWO]); + RegisterGlobalGestureListener(gestureListenerType, outPhases, listener); + napi_close_handle_scope(env, scope); + return nullptr; +} + +napi_value GestureObserver::RemoveGlobalGestureListener(napi_env env, napi_callback_info info) +{ + napi_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_handle_scope(env, &scope)); + size_t argc = ARG_COUNT_TWO; + napi_value argv[ARG_COUNT_TWO] = { nullptr }; + napi_get_cb_info(env, info, &argc, argv, nullptr, nullptr); + if (argc != ARG_COUNT_ONE && argc != ARG_COUNT_TWO) { + napi_close_handle_scope(env, scope); + LOGE("Invalid arguments"); + return nullptr; + } + NG::GestureListenerType gestureListenerType; + if (!ParseGestureListenerType(env, argv[PARAM_INDEX_ZERO], gestureListenerType)) { + napi_close_handle_scope(env, scope); + return nullptr; + } + if (argc == ARG_COUNT_ONE) { + UnRegisterGlobalGestureListener(gestureListenerType, nullptr); + } + if (argc == ARG_COUNT_TWO && GestureObserverListener::MatchValueType(env, argv[PARAM_INDEX_ONE], napi_function)) { + UnRegisterGlobalGestureListener(gestureListenerType, argv[PARAM_INDEX_ONE]); + } + napi_close_handle_scope(env, scope); + return nullptr; +} + +void GestureObserver::RegisterGlobalGestureListener(NG::GestureListenerType gestureListenerType, + const std::unordered_set& outPhase, const std::shared_ptr& listener) +{ + std::lock_guard lock(mutex_); + auto iter = GestureObserverListeners_.find(gestureListenerType); + if (iter == GestureObserverListeners_.end()) { + std::unordered_map>> phaseMap; + for (const auto& phase : outPhase) { + phaseMap.emplace(phase, std::list>({ listener })); + } + GestureObserverListeners_.emplace(gestureListenerType, std::move(phaseMap)); + return; + } + auto& holder = iter->second; + for (const auto& phase : outPhase) { + auto phaseIter = holder.find(phase); + if (phaseIter == holder.end()) { + holder.emplace(phase, std::list> { listener }); + } else { + auto& listenerList = phaseIter->second; + if (std::find(listenerList.begin(), listenerList.end(), listener) != listenerList.end()) { + continue; + } + listenerList.emplace_back(listener); + } + } +} + +void GestureObserver::UnRegisterGlobalGestureListener(NG::GestureListenerType gestureListenerType, napi_value callback) +{ + std::lock_guard lock(mutex_); + auto iter = GestureObserverListeners_.find(gestureListenerType); + if (iter == GestureObserverListeners_.end()) { + return; + } + auto& phaseMap = iter->second; + if (callback == nullptr) { + phaseMap.clear(); + return; + } + + for (auto phaseIter = phaseMap.begin(); phaseIter != phaseMap.end();) { + auto& listenerList = phaseIter->second; + listenerList.erase( + std::remove_if( + listenerList.begin(), + listenerList.end(), + [callback](const std::shared_ptr& registeredListener) { + return registeredListener->NapiEqual(callback); + }), + listenerList.end() + ); + if (listenerList.empty()) { + phaseIter = phaseMap.erase(phaseIter); + } else { + ++phaseIter; + } + } + + if (phaseMap.empty()) { + GestureObserverListeners_.erase(iter); + } +} + +void GestureObserver::HandleGestureAccept(NG::GestureListenerType gestureListenerType, + const GestureEvent& gestureEventInfo, const RefPtr& current, + const RefPtr& frameNode, NG::GestureActionPhase phase) +{ + std::lock_guard lock(mutex_); + if (!current) { + TAG_LOGW(AceLogTag::ACE_OBSERVER, "Handle gesture accept failed, recognizer is null"); + return; + } + auto env = GetCurrentNapiEnv(); + napi_handle_scope scope = nullptr; + auto status = napi_open_handle_scope(env, &scope); + if (status != napi_ok) { + return; + } + + auto iter = GestureObserverListeners_.find(gestureListenerType); + if (iter == GestureObserverListeners_.end()) { + napi_close_handle_scope(env, scope); + return; + } + auto& holder = iter->second; + auto phaseIter = holder.find(phase); + if (phaseIter == holder.end()) { + napi_close_handle_scope(env, scope); + return; + } + for (const auto& listener : phaseIter->second) { + listener->OnGestureStateChange(gestureEventInfo, current, frameNode, phase); + } + napi_close_handle_scope(env, scope); +} + +napi_env GestureObserver::GetCurrentNapiEnv() +{ + auto engine = EngineHelper::GetCurrentEngine(); + CHECK_NULL_RETURN(engine, nullptr); + NativeEngine* nativeEngine = engine->GetNativeEngine(); + CHECK_NULL_RETURN(nativeEngine, nullptr); + return reinterpret_cast(nativeEngine); +} +} // namespace OHOS::Ace::Napi diff --git a/interfaces/napi/kits/observer/gesture/gesture_observer.h b/interfaces/napi/kits/observer/gesture/gesture_observer.h new file mode 100644 index 0000000000000000000000000000000000000000..5be96d039415ee51f85c18b4c458da41c4f63390 --- /dev/null +++ b/interfaces/napi/kits/observer/gesture/gesture_observer.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_ACE_INTERFACES_GESTURE_GESTURE_OBSERVER_H +#define FOUNDATION_ACE_INTERFACES_GESTURE_GESTURE_OBSERVER_H + +#include +#include +#include +#include +#include + +#include "napi/native_api.h" + +#include "base/memory/ace_type.h" +#include "core/gestures/gesture_event.h" + +namespace OHOS::Ace::NG { +enum class GestureListenerType; +enum class GestureActionPhase; +class NGGestureRecognizer; +class FrameNode; +} // namespace OHOS::Ace::NG + +namespace OHOS::Ace::Napi { + +class UIObserverListener; + +class GestureObserver final { +public: + GestureObserver() = default; + ~GestureObserver() = default; + static napi_status DefineGestureObserver(napi_env env, napi_value exports); + +private: + static napi_value AddGlobalGestureListener(napi_env env, napi_callback_info info); + static napi_value RemoveGlobalGestureListener(napi_env env, napi_callback_info info); + static void RegisterGlobalGestureListener(NG::GestureListenerType gestureListenerType, + const std::unordered_set& outPhase, + const std::shared_ptr& listener); + static void UnRegisterGlobalGestureListener(NG::GestureListenerType gestureListenerType, napi_value callback); + static napi_env GetCurrentNapiEnv(); + static void HandleGestureAccept(NG::GestureListenerType gestureListenerType, const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr& frameNode, + NG::GestureActionPhase phase); + + static std::unordered_map>>> + GestureObserverListeners_; + static bool isGestureHandleFuncSetted_; + static std::mutex mutex_; +}; + +} // namespace OHOS::Ace::Napi +#endif // FOUNDATION_ACE_INTERFACES_GESTURE_GESTURE_OBSERVER_H diff --git a/interfaces/napi/kits/observer/gesture/gesture_observer_listener.cpp b/interfaces/napi/kits/observer/gesture/gesture_observer_listener.cpp new file mode 100644 index 0000000000000000000000000000000000000000..ae0de481b4ab8a28d1e0c0025a0b013cb980d4d9 --- /dev/null +++ b/interfaces/napi/kits/observer/gesture/gesture_observer_listener.cpp @@ -0,0 +1,1063 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "gesture_observer_listener.h" + +#include "interfaces/inner_api/ace_kit/include/ui/base/utils/utils.h" +#include "interfaces/napi/kits/utils/napi_utils.h" +#include "js_native_api.h" +#include "js_native_api_types.h" +#include "native_engine/impl/ark/ark_native_engine.h" + +#include "base/utils/utils.h" +#include "bridge/common/utils/engine_helper.h" +#include "core/components_ng/gestures/recognizers/click_recognizer.h" +#include "core/components_ng/gestures/recognizers/gesture_recognizer.h" +#include "core/components_ng/gestures/recognizers/long_press_recognizer.h" +#include "core/components_ng/gestures/recognizers/multi_fingers_recognizer.h" +#include "core/components_ng/gestures/recognizers/pan_recognizer.h" +#include "core/components_ng/gestures/recognizers/pinch_recognizer.h" +#include "core/components_ng/gestures/recognizers/rotation_recognizer.h" +#include "core/components_ng/gestures/recognizers/swipe_recognizer.h" +#include "core/components_ng/pattern/scrollable/scrollable_pattern.h" +#include "core/components_ng/pattern/swiper/swiper_pattern.h" + +namespace OHOS::Ace::Napi { +namespace { +constexpr char GET_TAG[] = "getTag"; +constexpr char GET_TYPE[] = "getType"; +constexpr char IS_BUILT_IN[] = "isBuiltIn"; +constexpr char SET_ENABLED[] = "setEnabled"; +constexpr char IS_ENABLED[] = "isEnabled"; +constexpr char GET_STATE[] = "getState"; +constexpr char GET_EVENT_TARGET_INFO[] = "getEventTargetInfo"; +constexpr char IS_VALID[] = "isValid"; +constexpr char GET_ID[] = "getId"; +constexpr char IS_BEGIN[] = "isBegin"; +constexpr char IS_END[] = "isEnd"; +constexpr char GET_FINGER_COUNT[] = "getFingerCount"; +constexpr char IS_FINGER_COUNT_LIMIT[] = "isFingerCountLimit"; +constexpr char GET_DIRECTION[] = "getDirection"; +constexpr char GET_DISTANCE[] = "getDistance"; +constexpr char GET_DISTANCE_MAP[] = "getDistanceMap"; +constexpr char GET_PANGESTURE_OPTIONS[] = "getPanGestureOptions"; +constexpr char SET_DIRECTION[] = "setDirection"; +constexpr char SET_DISTANCE[] = "setDistance"; +constexpr char SET_FINGERS[] = "setFingers"; +constexpr char GET_TAP_COUNT[] = "getTapCount"; +constexpr char IS_REPEAT[] = "isRepeat"; +constexpr char GET_DURATION[] = "getDuration"; +constexpr char GET_ANGLE[] = "getAngle"; +constexpr char GET_VELOCITY_THRESHOLD[] = "getVelocityThreshold"; + +constexpr int32_t PARAM_SIZE_ZERO = 0; +constexpr int32_t PARAM_SIZE_ONE = 1; +constexpr int32_t PARAM_SIZE_TWO = 2; +constexpr Dimension DEFAULT_PAN_DISTANCE = 5.0_vp; +constexpr double DEFAULT_DISTANCE = 5; +constexpr int32_t DEFAULT_PAN_FINGER = 1; +constexpr int32_t DEFAULT_MAX_PAN_FINGERS = 10; + +enum class RecognizerType { MULTI_FINGERS, PAN }; + +struct MultiFingersRecognizerWrapper { + double distance = 0.0; + uint32_t direction = PanDirection::ALL; + RecognizerType type = RecognizerType::MULTI_FINGERS; + RefPtr recognizer; +}; + +struct PanRecognizerWrapper { + RefPtr recognizer = nullptr; + RefPtr panGestureOption = nullptr; + RecognizerType type = RecognizerType::PAN; +}; + +struct EventTargetInfoWrapper { + std::string inspectorId = ""; + WeakPtr weakPattern = nullptr; + EventTargetInfoWrapper(std::string inspectorId, WeakPtr pattern) + : inspectorId(inspectorId), weakPattern(std::move(pattern)) + {} + + bool IsBegin() const + { + auto pattern = weakPattern.Upgrade(); + if (!pattern) { + return false; + } + auto scrollablePattern = AceType::DynamicCast(pattern); + if (scrollablePattern) { + return scrollablePattern->IsAtTop(); + } + auto swiperPattern = AceType::DynamicCast(pattern); + if (swiperPattern) { + return swiperPattern->IsAtStart(); + } + return false; + } + + bool IsEnd() const + { + auto pattern = weakPattern.Upgrade(); + if (!pattern) { + return false; + } + auto scrollablePattern = AceType::DynamicCast(pattern); + if (scrollablePattern) { + return scrollablePattern->IsAtBottom(); + } + auto swiperPattern = AceType::DynamicCast(pattern); + if (swiperPattern) { + return swiperPattern->IsAtEnd(); + } + return false; + } +}; + +MultiFingersRecognizerWrapper* GetCurrentMultiFingersRecognizerWrapper( + napi_env env, napi_callback_info info, size_t* argc = nullptr, napi_value* argv = nullptr) +{ + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, argc, argv, &thisVar, nullptr)); + + void* rawWrapper = nullptr; + napi_status unwrapStatus = napi_unwrap(env, thisVar, &rawWrapper); + if (unwrapStatus != napi_ok) { + return nullptr; + } + auto* wrapper = static_cast(rawWrapper); + return (wrapper && wrapper->type == RecognizerType::MULTI_FINGERS && wrapper->recognizer) ? wrapper : nullptr; +} + +PanRecognizerWrapper* GetCurrentPanRecognizerWrapper( + napi_env env, napi_callback_info info, size_t* argc = nullptr, napi_value* argv = nullptr) +{ + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, argc, argv, &thisVar, nullptr)); + + void* rawWrapper = nullptr; + const napi_status unwrapStatus = napi_unwrap(env, thisVar, &rawWrapper); + if (unwrapStatus != napi_ok) { + return nullptr; + } + + auto* wrapper = static_cast(rawWrapper); + if (!wrapper || wrapper->type != RecognizerType::PAN || !wrapper->recognizer || !wrapper->panGestureOption) { + return nullptr; + } + + return wrapper; +} + +EventTargetInfoWrapper* GetEventTargetInfoWrapper( + napi_env env, napi_callback_info info, size_t* argc = nullptr, napi_value* argv = nullptr) +{ + napi_value thisVar = nullptr; + NAPI_CALL(env, napi_get_cb_info(env, info, argc, argv, &thisVar, nullptr)); + + void* rawWrapper = nullptr; + napi_status unwrapStatus = napi_unwrap(env, thisVar, &rawWrapper); + if (unwrapStatus != napi_ok) { + return nullptr; + } + auto* wrapper = static_cast(rawWrapper); + return wrapper; +} + +void PaesePanDirection(napi_env env, napi_value value, PanDirection& panDirection) +{ + uint32_t typeValue; + napi_get_value_uint32(env, value, &typeValue); + switch (typeValue) { + case static_cast(PanDirection::NONE): + panDirection.type = PanDirection::NONE; + return; + case static_cast(PanDirection::LEFT): + panDirection.type = PanDirection::LEFT; + return; + case static_cast(PanDirection::RIGHT): + panDirection.type = PanDirection::RIGHT; + return; + case static_cast(PanDirection::HORIZONTAL): + panDirection.type = PanDirection::HORIZONTAL; + return; + case static_cast(PanDirection::UP): + panDirection.type = PanDirection::UP; + return; + case static_cast(PanDirection::DOWN): + panDirection.type = PanDirection::DOWN; + return; + case static_cast(PanDirection::VERTICAL): + panDirection.type = PanDirection::VERTICAL; + return; + case static_cast(PanDirection::ALL): + panDirection.type = PanDirection::ALL; + return; + default: + panDirection.type = PanDirection::ALL; + return; + } +} + +static napi_value GetTag(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + MultiFingersRecognizerWrapper* current = GetCurrentMultiFingersRecognizerWrapper(env, info); + if (!current || !current->recognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_value result = nullptr; + auto gestureInfo = current->recognizer->GetGestureInfo(); + if (!gestureInfo) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + std::string tag = gestureInfo->GetTag().value_or(""); + napi_create_string_utf8(env, tag.c_str(), NAPI_AUTO_LENGTH, &result); + napi_value newResult = nullptr; + napi_escape_handle(env, scope, result, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +static napi_value GetType(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + MultiFingersRecognizerWrapper* current = GetCurrentMultiFingersRecognizerWrapper(env, info); + if (!current || !current->recognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_value result = nullptr; + auto gestureInfo = current->recognizer->GetGestureInfo(); + if (!gestureInfo) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_create_int32(env, static_cast(gestureInfo->GetRecognizerType()), &result); + napi_value newResult = nullptr; + napi_escape_handle(env, scope, result, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +static napi_value IsBuiltIn(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + MultiFingersRecognizerWrapper* current = GetCurrentMultiFingersRecognizerWrapper(env, info); + if (!current || !current->recognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_value result = nullptr; + auto gestureInfo = current->recognizer->GetGestureInfo(); + if (!gestureInfo) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_get_boolean(env, gestureInfo->IsSystemGesture(), &result); + napi_value newResult = nullptr; + napi_escape_handle(env, scope, result, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +static napi_value SetEnabled(napi_env env, napi_callback_info info) +{ + napi_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_handle_scope(env, &scope)); + size_t argc = PARAM_SIZE_ONE; + napi_value argv[PARAM_SIZE_ONE] = { nullptr }; + MultiFingersRecognizerWrapper* current = GetCurrentMultiFingersRecognizerWrapper(env, info, &argc, argv); + if (!current || !current->recognizer) { + napi_close_handle_scope(env, scope); + return nullptr; + } + napi_valuetype valueType = napi_undefined; + if (napi_typeof(env, argv[PARAM_SIZE_ZERO], &valueType)) { + napi_close_handle_scope(env, scope); + return nullptr; + } + if (valueType != napi_boolean) { + napi_close_handle_scope(env, scope); + return nullptr; + } + bool isEnabled = false; + napi_get_value_bool(env, argv[PARAM_SIZE_ZERO], &isEnabled); + current->recognizer->SetEnabled(isEnabled); + napi_close_handle_scope(env, scope); + return nullptr; +} + +static napi_value IsEnabled(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + MultiFingersRecognizerWrapper* current = GetCurrentMultiFingersRecognizerWrapper(env, info); + if (!current || !current->recognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_value result = nullptr; + napi_get_boolean(env, current->recognizer->IsEnabled(), &result); + napi_value newResult = nullptr; + napi_escape_handle(env, scope, result, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +static napi_value GetState(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + MultiFingersRecognizerWrapper* current = GetCurrentMultiFingersRecognizerWrapper(env, info); + if (!current || !current->recognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_value result = nullptr; + napi_create_int32(env, static_cast(current->recognizer->GetRefereeState()), &result); + napi_value newResult = nullptr; + napi_escape_handle(env, scope, result, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +static napi_value GetId(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + EventTargetInfoWrapper* wrapper = GetEventTargetInfoWrapper(env, info); + if (!wrapper) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + + napi_value result = nullptr; + napi_create_string_utf8(env, wrapper->inspectorId.c_str(), NAPI_AUTO_LENGTH, &result); + napi_value newResult = nullptr; + napi_escape_handle(env, scope, result, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +static napi_value IsBegin(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + EventTargetInfoWrapper* wrapper = GetEventTargetInfoWrapper(env, info); + if (!wrapper) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_value result = nullptr; + napi_get_boolean(env, wrapper->IsBegin(), &result); + napi_value newResult = nullptr; + napi_escape_handle(env, scope, result, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +static napi_value IsEnd(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + EventTargetInfoWrapper* wrapper = GetEventTargetInfoWrapper(env, info); + if (!wrapper) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_value result = nullptr; + napi_get_boolean(env, wrapper->IsEnd(), &result); + napi_value newResult = nullptr; + napi_escape_handle(env, scope, result, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +static napi_value CreateEventTargetInfo( + napi_env env, const RefPtr& pattern, const std::string& inspectorId) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + napi_value result = nullptr; + napi_create_object(env, &result); + + auto* wrapper = new EventTargetInfoWrapper(std::move(inspectorId), pattern); + auto status = napi_wrap( + env, result, wrapper, + [](napi_env env, void* data, void* hint) { + auto* wrapper = static_cast(data); + if (wrapper) { + delete wrapper; + } + }, + nullptr, nullptr); + if (status != napi_ok) { + LOGE("Failed to wrap native object"); + delete wrapper; + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_value funcValue = nullptr; + napi_create_function(env, GET_ID, NAPI_AUTO_LENGTH, GetId, nullptr, &funcValue); + napi_set_named_property(env, result, GET_ID, funcValue); + if (pattern) { + napi_create_function(env, IS_BEGIN, NAPI_AUTO_LENGTH, IsBegin, nullptr, &funcValue); + napi_set_named_property(env, result, IS_BEGIN, funcValue); + napi_create_function(env, IS_END, NAPI_AUTO_LENGTH, IsEnd, nullptr, &funcValue); + napi_set_named_property(env, result, IS_END, funcValue); + } + napi_value newResult = nullptr; + napi_escape_handle(env, scope, result, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +static napi_value GetEventTargetInfo(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + MultiFingersRecognizerWrapper* current = GetCurrentMultiFingersRecognizerWrapper(env, info); + if (!current || !current->recognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_value result = nullptr; + napi_create_object(env, &result); + auto attachNode = current->recognizer->GetAttachedNode().Upgrade(); + if (!attachNode) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + RefPtr pattern = nullptr; + auto scrollablePattern = attachNode->GetPattern(); + if (scrollablePattern) { + pattern = scrollablePattern; + } + auto swiperPattern = attachNode->GetPattern(); + if (swiperPattern) { + pattern = swiperPattern; + } + result = CreateEventTargetInfo(env, pattern, attachNode->GetInspectorIdValue("")); + napi_value newResult = nullptr; + napi_escape_handle(env, scope, result, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +static napi_value IsValid(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + MultiFingersRecognizerWrapper* current = GetCurrentMultiFingersRecognizerWrapper(env, info); + if (!current || !current->recognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_value result = nullptr; + napi_get_boolean(env, current->recognizer->IsInResponseLinkRecognizers(), &result); + napi_value newResult = nullptr; + napi_escape_handle(env, scope, result, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +static napi_value GetFingerCount(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + MultiFingersRecognizerWrapper* current = GetCurrentMultiFingersRecognizerWrapper(env, info); + if (!current || !current->recognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_value result = nullptr; + napi_create_int32(env, static_cast(current->recognizer->GetFingers()), &result); + napi_value newResult = nullptr; + napi_escape_handle(env, scope, result, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +static napi_value IsFingerCountLimit(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + MultiFingersRecognizerWrapper* current = GetCurrentMultiFingersRecognizerWrapper(env, info); + if (!current || !current->recognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_value result = nullptr; + napi_get_boolean(env, current->recognizer->GetLimitFingerCount(), &result); + napi_value newResult = nullptr; + napi_escape_handle(env, scope, result, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +static napi_value GetDistance(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + auto context = PipelineContext::GetCurrentContextSafely(); + if (!context) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_value thisArg; + napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr); + double distance = DEFAULT_DISTANCE; + PanRecognizerWrapper* wrapper = nullptr; + napi_status unwrapStatus = napi_unwrap(env, thisArg, reinterpret_cast(&wrapper)); + if (unwrapStatus == napi_ok && wrapper && wrapper->type == RecognizerType::PAN && wrapper->panGestureOption) { + distance = wrapper->panGestureOption->GetDistance(); + } else { + MultiFingersRecognizerWrapper* multiFingersRecognizerWrapper = nullptr; + napi_status status = napi_unwrap(env, thisArg, reinterpret_cast(&multiFingersRecognizerWrapper)); + if (status == napi_ok && multiFingersRecognizerWrapper && multiFingersRecognizerWrapper->recognizer) { + if (auto recognizer = + AceType::DynamicCast(multiFingersRecognizerWrapper->recognizer)) { + distance = recognizer->GetDistance(); + } + if (auto recognizer = AceType::DynamicCast(multiFingersRecognizerWrapper->recognizer)) { + distance = multiFingersRecognizerWrapper->distance; + } + } + } + + napi_value napiDistance = nullptr; + napi_create_double( + env, RoundToMaxPrecision(context->ConvertPxToVp(Dimension(distance, DimensionUnit::PX))), &napiDistance); + napi_value newResult = nullptr; + napi_escape_handle(env, scope, napiDistance, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +static napi_value GetDirection(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + napi_value thisArg; + napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr); + PanRecognizerWrapper* wrapper = nullptr; + auto status = napi_unwrap(env, thisArg, reinterpret_cast(&wrapper)); + uint32_t type = PanDirection::ALL; + if (status == napi_ok && wrapper && wrapper->type == RecognizerType::PAN && wrapper->panGestureOption) { + type = wrapper->panGestureOption->GetDirection().type; + } else { + MultiFingersRecognizerWrapper* multiFingersRecognizerWrapper = nullptr; + napi_unwrap(env, thisArg, reinterpret_cast(&multiFingersRecognizerWrapper)); + if (multiFingersRecognizerWrapper && multiFingersRecognizerWrapper->recognizer) { + if (auto recognizer = AceType::DynamicCast(multiFingersRecognizerWrapper->recognizer)) { + type = multiFingersRecognizerWrapper->direction; + } + } + } + napi_value napiDirection = nullptr; + napi_create_uint32(env, type, &napiDirection); + napi_value newResult = nullptr; + napi_escape_handle(env, scope, napiDirection, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +static napi_value GetSwipeDirection(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + MultiFingersRecognizerWrapper* current = GetCurrentMultiFingersRecognizerWrapper(env, info); + if (!current || !current->recognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + auto recognizer = AceType::DynamicCast(current->recognizer); + if (!recognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_value napiDirection = nullptr; + napi_create_uint32(env, recognizer->GetDirection().type, &napiDirection); + napi_value newResult = nullptr; + napi_escape_handle(env, scope, napiDirection, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +static napi_value GetDistanceMap(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + MultiFingersRecognizerWrapper* current = GetCurrentMultiFingersRecognizerWrapper(env, info); + if (!current || !current->recognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + auto recognizer = AceType::DynamicCast(current->recognizer); + if (!recognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + auto panDistanceMap = recognizer->GetDistanceMap(); + auto context = PipelineContext::GetCurrentContextSafely(); + if (!context) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_value globalObj = nullptr; + napi_value nativeMap = nullptr; + napi_value constructor = nullptr; + napi_get_global(env, &globalObj); + napi_get_named_property(env, globalObj, "Map", &constructor); + napi_new_instance(env, constructor, 0, NULL, &nativeMap); + napi_value setFunc = nullptr; + napi_get_named_property(env, nativeMap, "set", &setFunc); + napi_value result; + for (const auto& item : panDistanceMap) { + double distance = context->ConvertPxToVp(Dimension(item.second, DimensionUnit::PX)); + double roundedDistance = RoundToMaxPrecision(distance); + napi_value key; + napi_value value; + napi_create_int32(env, static_cast(item.first), &key); + napi_create_double(env, roundedDistance, &value); + napi_value argv[] = { key, value }; + napi_call_function(env, nativeMap, setFunc, PARAM_SIZE_TWO, argv, &result); + } + napi_value newResult = nullptr; + napi_escape_handle(env, scope, nativeMap, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +static napi_value SetDirection(napi_env env, napi_callback_info info) +{ + napi_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_handle_scope(env, &scope)); + size_t argc = PARAM_SIZE_ONE; + napi_value argv[PARAM_SIZE_ONE] = { nullptr }; + + PanRecognizerWrapper* wrapper = GetCurrentPanRecognizerWrapper(env, info, &argc, argv); + if (!wrapper) { + napi_close_handle_scope(env, scope); + return nullptr; + } + if (!wrapper->panGestureOption) { + napi_close_handle_scope(env, scope); + return nullptr; + } + PanDirection panDirection; + if (argc != PARAM_SIZE_ONE || !GestureObserverListener::MatchValueType(env, argv[PARAM_SIZE_ZERO], napi_number)) { + panDirection.type = PanDirection::ALL; + } else { + PaesePanDirection(env, argv[PARAM_SIZE_ZERO], panDirection); + } + + wrapper->panGestureOption->SetDirection(panDirection); + napi_close_handle_scope(env, scope); + return nullptr; +} + +static napi_value SetDistance(napi_env env, napi_callback_info info) +{ + napi_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_handle_scope(env, &scope)); + size_t argc = PARAM_SIZE_ONE; + napi_value argv[PARAM_SIZE_ONE] = { nullptr }; + + PanRecognizerWrapper* wrapper = GetCurrentPanRecognizerWrapper(env, info, &argc, argv); + if (!wrapper) { + napi_close_handle_scope(env, scope); + return nullptr; + } + if (!wrapper->panGestureOption) { + napi_close_handle_scope(env, scope); + return nullptr; + } + if (argc != PARAM_SIZE_ONE || !GestureObserverListener::MatchValueType(env, argv[PARAM_SIZE_ZERO], napi_number)) { + wrapper->panGestureOption->SetDistance(DEFAULT_PAN_DISTANCE.ConvertToPx()); + } else { + double distance; + napi_get_value_double(env, argv[PARAM_SIZE_ZERO], &distance); + if (LessNotEqual(distance, 0.0)) { + wrapper->panGestureOption->SetDistance(DEFAULT_PAN_DISTANCE.ConvertToPx()); + } else { + wrapper->panGestureOption->SetDistance(Dimension(distance, DimensionUnit::VP).ConvertToPx()); + } + } + napi_close_handle_scope(env, scope); + return nullptr; +} + +static napi_value SetFingers(napi_env env, napi_callback_info info) +{ + napi_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_handle_scope(env, &scope)); + size_t argc = PARAM_SIZE_ONE; + napi_value argv[PARAM_SIZE_ONE] = { nullptr }; + + PanRecognizerWrapper* wrapper = GetCurrentPanRecognizerWrapper(env, info, &argc, argv); + if (!wrapper) { + napi_close_handle_scope(env, scope); + return nullptr; + } + if (!wrapper->panGestureOption) { + napi_close_handle_scope(env, scope); + return nullptr; + } + if (argc != PARAM_SIZE_ONE || !GestureObserverListener::MatchValueType(env, argv[PARAM_SIZE_ZERO], napi_number)) { + wrapper->panGestureOption->SetFingers(DEFAULT_PAN_FINGER); + } else { + int32_t fingers; + napi_get_value_int32(env, argv[PARAM_SIZE_ZERO], &fingers); + fingers = fingers <= DEFAULT_PAN_FINGER ? DEFAULT_PAN_FINGER : fingers; + fingers = fingers > DEFAULT_MAX_PAN_FINGERS ? DEFAULT_PAN_FINGER : fingers; + wrapper->panGestureOption->SetFingers(DEFAULT_PAN_FINGER); + } + napi_close_handle_scope(env, scope); + return nullptr; +} + +static napi_value GetTapCount(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + MultiFingersRecognizerWrapper* current = GetCurrentMultiFingersRecognizerWrapper(env, info); + if (!current || !current->recognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + RefPtr tapRecognizer = AceType::DynamicCast(current->recognizer); + if (!tapRecognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_value count = nullptr; + napi_create_uint32(env, static_cast(tapRecognizer->GetCount()), &count); + napi_value newResult = nullptr; + napi_escape_handle(env, scope, count, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +static napi_value IsRepeat(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + MultiFingersRecognizerWrapper* current = GetCurrentMultiFingersRecognizerWrapper(env, info); + if (!current || !current->recognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + RefPtr longPressRecognizer = + AceType::DynamicCast(current->recognizer); + if (!longPressRecognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_value result = nullptr; + napi_get_boolean(env, longPressRecognizer->GetIsRepeat(), &result); + napi_value newResult = nullptr; + napi_escape_handle(env, scope, result, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +static napi_value GetDuration(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + MultiFingersRecognizerWrapper* current = GetCurrentMultiFingersRecognizerWrapper(env, info); + if (!current || !current->recognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + RefPtr longPressRecognizer = + AceType::DynamicCast(current->recognizer); + if (!longPressRecognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_value count = nullptr; + napi_create_int32(env, longPressRecognizer->GetDuration(), &count); + napi_value newResult = nullptr; + napi_escape_handle(env, scope, count, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +static napi_value GetAngle(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + MultiFingersRecognizerWrapper* current = GetCurrentMultiFingersRecognizerWrapper(env, info); + if (!current || !current->recognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + RefPtr rotationRecognizer = + AceType::DynamicCast(current->recognizer); + if (!rotationRecognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_value angle = nullptr; + napi_create_double(env, rotationRecognizer->GetAngle(), &angle); + napi_value newResult = nullptr; + napi_escape_handle(env, scope, angle, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +static napi_value GetVelocityThreshold(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + MultiFingersRecognizerWrapper* current = GetCurrentMultiFingersRecognizerWrapper(env, info); + if (!current || !current->recognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + RefPtr swipeRecognizer = AceType::DynamicCast(current->recognizer); + if (!swipeRecognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + auto context = PipelineContext::GetCurrentContextSafely(); + if (!context) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + napi_value speed = nullptr; + napi_create_double(env, + RoundToMaxPrecision(context->ConvertPxToVp(Dimension(swipeRecognizer->GetSpeed(), DimensionUnit::PX))), &speed); + napi_value newResult = nullptr; + napi_escape_handle(env, scope, speed, &newResult); + napi_close_escapable_handle_scope(env, scope); + return newResult; +} + +RefPtr CreatePanGestureOption(const RefPtr& panRecognizer) +{ + auto panGestureOption = AceType::MakeRefPtr(); + panGestureOption->SetFingers(panRecognizer->GetFingers()); + panGestureOption->SetDistance(panRecognizer->GetDistance()); + panGestureOption->SetDirection(panRecognizer->GetDirection()); + return panGestureOption; +} + +bool WrapPanGestureOption(napi_env env, napi_value result, const RefPtr& panRecognizer, + const RefPtr& panGestureOption) +{ + auto* wrapper = new PanRecognizerWrapper { panRecognizer, panGestureOption }; + auto status = napi_wrap( + env, result, wrapper, + [](napi_env env, void* data, void* hint) { + auto* current = static_cast(data); + if (current) { + delete current; + } + }, + nullptr, nullptr); + if (status != napi_ok) { + LOGE("Failed to wrap native object"); + delete wrapper; + return false; + } + return true; +} + +void BindPanGestureFunctions(napi_env env, napi_value result) +{ + const std::vector> functions = { { GET_DIRECTION, GetDirection }, + { GET_DISTANCE, GetDistance }, { SET_DIRECTION, SetDirection }, { SET_DISTANCE, SetDistance }, + { SET_FINGERS, SetFingers } }; + + for (const auto& [name, func] : functions) { + napi_value funcValue = nullptr; + napi_create_function(env, name, NAPI_AUTO_LENGTH, func, nullptr, &funcValue); + napi_set_named_property(env, result, name, funcValue); + } +} + +static napi_value CreatePanGestureOptionsObject(napi_env env, MultiFingersRecognizerWrapper* wrapper) +{ + auto panRecognizer = AceType::DynamicCast(wrapper->recognizer); + if (!panRecognizer) { + return nullptr; + } + + napi_value result = nullptr; + napi_create_object(env, &result); + + auto panGestureOption = CreatePanGestureOption(panRecognizer); + if (!WrapPanGestureOption(env, result, panRecognizer, panGestureOption)) { + return nullptr; + } + + BindPanGestureFunctions(env, result); + return result; +} + +static napi_value GetPanGestureOptions(napi_env env, napi_callback_info info) +{ + napi_escapable_handle_scope scope = nullptr; + NAPI_CALL(env, napi_open_escapable_handle_scope(env, &scope)); + + auto* wrapper = GetCurrentMultiFingersRecognizerWrapper(env, info); + if (!wrapper || !wrapper->recognizer) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + + napi_value result = CreatePanGestureOptionsObject(env, wrapper); + if (!result) { + napi_close_escapable_handle_scope(env, scope); + return nullptr; + } + + napi_value escapedResult = nullptr; + napi_escape_handle(env, scope, result, &escapedResult); + napi_close_escapable_handle_scope(env, scope); + return escapedResult; +} + +void BindCommonFunctions(napi_env env, napi_value objValue) +{ + const std::vector> functions = { { GET_TAG, GetTag }, { GET_TYPE, GetType }, + { IS_BUILT_IN, IsBuiltIn }, { SET_ENABLED, SetEnabled }, { IS_ENABLED, IsEnabled }, { GET_STATE, GetState }, + { GET_EVENT_TARGET_INFO, GetEventTargetInfo }, { IS_VALID, IsValid }, { GET_FINGER_COUNT, GetFingerCount }, + { IS_FINGER_COUNT_LIMIT, IsFingerCountLimit } }; + + for (const auto& [name, func] : functions) { + napi_value funcValue = nullptr; + napi_create_function(env, name, NAPI_AUTO_LENGTH, func, nullptr, &funcValue); + napi_set_named_property(env, objValue, name, funcValue); + } +} + +bool WrapRecognizer(napi_env env, napi_value objValue, MultiFingersRecognizerWrapper* wrapper) +{ + auto status = napi_wrap( + env, objValue, wrapper, + [](napi_env env, void* data, void* hint) { + auto* current = static_cast(data); + if (current) { + delete current; + } + }, + nullptr, nullptr); + if (status != napi_ok) { + LOGE("napi_wrap failed"); + return false; + } + return true; +} + +void BindRecognizerSpecificFunctions(napi_env env, napi_value objValue, GestureTypeName typeName) +{ + static const std::unordered_map>> + typeFunctions = { { GestureTypeName::PAN_GESTURE, + { { GET_PANGESTURE_OPTIONS, GetPanGestureOptions }, { GET_DIRECTION, GetDirection }, + { GET_DISTANCE, GetDistance }, { GET_DISTANCE_MAP, GetDistanceMap } } }, + { GestureTypeName::PINCH_GESTURE, { { GET_DISTANCE, GetDistance } } }, + { GestureTypeName::TAP_GESTURE, { { GET_TAP_COUNT, GetTapCount } } }, + { GestureTypeName::LONG_PRESS_GESTURE, { { IS_REPEAT, IsRepeat }, { GET_DURATION, GetDuration } } }, + { GestureTypeName::ROTATION_GESTURE, { { GET_ANGLE, GetAngle } } }, + { GestureTypeName::SWIPE_GESTURE, + { { GET_VELOCITY_THRESHOLD, GetVelocityThreshold }, { GET_DIRECTION, GetSwipeDirection } } } }; + + auto it = typeFunctions.find(typeName); + if (it == typeFunctions.end()) { + return; + } + + for (const auto& [name, func] : it->second) { + napi_value funcValue = nullptr; + napi_create_function(env, name, NAPI_AUTO_LENGTH, func, nullptr, &funcValue); + napi_set_named_property(env, objValue, name, funcValue); + } +} + +MultiFingersRecognizerWrapper* CreateMultiFingersWrapper(const RefPtr& recognizer) +{ + auto* wrapper = new MultiFingersRecognizerWrapper(); + wrapper->recognizer = recognizer; + + if (auto panRecognizer = AceType::DynamicCast(recognizer)) { + wrapper->distance = panRecognizer->GetDistance(); + wrapper->direction = panRecognizer->GetDirection().type; + } + return wrapper; +} +} // namespace + +void GestureObserverListener::AddGestureRecognizerInfo( + napi_env env, napi_value objValueGestureRecognizer, const RefPtr& current) +{ + napi_handle_scope scope = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_open_handle_scope(env, &scope)); + + auto multiFingersRecognizer = AceType::DynamicCast(current); + if (!multiFingersRecognizer) { + napi_close_handle_scope(env, scope); + return; + } + + auto* wrapper = CreateMultiFingersWrapper(multiFingersRecognizer); + if (!wrapper) { + napi_close_handle_scope(env, scope); + return; + } + + if (!WrapRecognizer(env, objValueGestureRecognizer, wrapper)) { + delete wrapper; + } + + BindCommonFunctions(env, objValueGestureRecognizer); + CreateRecognizerObject(env, objValueGestureRecognizer, current); + napi_close_handle_scope(env, scope); +} + +void GestureObserverListener::CreateRecognizerObject( + napi_env env, napi_value objValue, const RefPtr& current) +{ + napi_handle_scope scope = nullptr; + NAPI_CALL_RETURN_VOID(env, napi_open_handle_scope(env, &scope)); + + auto gestureInfo = current->GetGestureInfo(); + if (!gestureInfo) { + napi_close_handle_scope(env, scope); + return; + } + + BindRecognizerSpecificFunctions(env, objValue, gestureInfo->GetRecognizerType()); + napi_close_handle_scope(env, scope); +} + +bool GestureObserverListener::MatchValueType(napi_env env, napi_value value, napi_valuetype targetType) +{ + napi_valuetype valueType = napi_undefined; + napi_typeof(env, value, &valueType); + return valueType == targetType; +} + +} // namespace OHOS::Ace::Napi diff --git a/interfaces/napi/kits/observer/gesture/gesture_observer_listener.h b/interfaces/napi/kits/observer/gesture/gesture_observer_listener.h new file mode 100644 index 0000000000000000000000000000000000000000..5e4f51db8282b097fb4197f98e55a55d9d0356d0 --- /dev/null +++ b/interfaces/napi/kits/observer/gesture/gesture_observer_listener.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2025 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_ACE_INTERFACES_GESTURE_GESTURE_OBSERVER_LISTENER_H +#define FOUNDATION_ACE_INTERFACES_GESTURE_GESTURE_OBSERVER_LISTENER_H + +#include "napi/native_api.h" + +#include "base/memory/ace_type.h" + +namespace OHOS::Ace::NG { +class NGGestureRecognizer; +} // namespace OHOS::Ace::NG + +namespace OHOS::Ace::Napi { +class GestureObserverListener final { +public: + GestureObserverListener() = default; + ~GestureObserverListener() = default; + static void AddGestureRecognizerInfo( + napi_env env, napi_value objValueGestureRecognizer, const RefPtr& current); + static void CreateRecognizerObject( + napi_env env, napi_value objValueGestureRecognizer, const RefPtr& current); + static bool MatchValueType(napi_env env, napi_value value, napi_valuetype targetType); +}; + +} // namespace OHOS::Ace::Napi +#endif // FOUNDATION_ACE_INTERFACES_GESTURE_GESTURE_OBSERVER_LISTENER_H diff --git a/interfaces/napi/kits/observer/js_ui_observer.cpp b/interfaces/napi/kits/observer/js_ui_observer.cpp index 55c457ec0699bff735d3f4f5ac76cfc652d5e870..e3f55f83d11fd8641a9d9b64a7a49140233806f8 100644 --- a/interfaces/napi/kits/observer/js_ui_observer.cpp +++ b/interfaces/napi/kits/observer/js_ui_observer.cpp @@ -19,6 +19,7 @@ #include "core/common/ace_engine.h" #include "core/components_ng/base/inspector.h" #include "core/components_ng/base/node_render_status_monitor.h" +#include "interfaces/napi/kits/observer/gesture/gesture_observer.h" #include "interfaces/napi/kits/utils/napi_utils.h" @@ -1591,6 +1592,7 @@ static napi_value UIObserverExport(napi_env env, napi_value exports) }; NAPI_CALL( env, napi_define_properties(env, exports, sizeof(uiObserverDesc) / sizeof(uiObserverDesc[0]), uiObserverDesc)); + NAPI_CALL(env, GestureObserver::DefineGestureObserver(env, exports)); return exports; } diff --git a/interfaces/napi/kits/observer/ui_observer_listener.cpp b/interfaces/napi/kits/observer/ui_observer_listener.cpp index 190aaeb18fd24247b825e65f7b9c7eafd22e8f3d..0595e5bf4a4a80d7c5b231221cde27d38f105ba6 100644 --- a/interfaces/napi/kits/observer/ui_observer_listener.cpp +++ b/interfaces/napi/kits/observer/ui_observer_listener.cpp @@ -16,395 +16,17 @@ #include "ui_observer_listener.h" #include "js_native_api.h" #include "core/event/ace_events.h" +#include "interfaces/napi/kits/observer/gesture/gesture_observer_listener.h" namespace OHOS::Ace::Napi { namespace { constexpr char NAV_BAR[] = "navBar"; -constexpr char GET_TAG[] = "getTag"; -constexpr char GET_TYPE[] = "getType"; -constexpr char IS_BUILT_IN[] = "isBuiltIn"; -constexpr char SET_ENABLED[] = "setEnabled"; -constexpr char IS_ENABLED[] = "isEnabled"; -constexpr char GET_STATE[] = "getState"; -constexpr char GET_EVENT_TARGET_INFO[] = "getEventTargetInfo"; -constexpr char IS_VALID[] = "isValid"; -constexpr char GET_ID[] = "getId"; constexpr char GET_MODIFIER_KEY_STATE[] = "getModifierKeyState"; -constexpr char GET_FINGER_COUNT[] = "getFingerCount"; -constexpr char IS_FINGER_COUNT_LIMIT[] = "isFingerCountLimit"; -constexpr char GET_DIRECTION[] = "getDirection"; -constexpr char GET_DISTANCE[] = "getDistance"; -constexpr char GET_PANGESTURE_OPTIONS[] = "getPanGestureOptions"; -constexpr char SET_DIRECTION[] = "setDirection"; -constexpr char SET_DISTANCE[] = "setDistance"; -constexpr char SET_FINGERS[] = "setFingers"; -constexpr int32_t PARAM_SIZE_ZERO = 0; constexpr int32_t PARAM_SIZE_ONE = 1; constexpr int32_t PARAM_SIZE_TWO = 2; constexpr int32_t PARAM_SIZE_THREE = 3; constexpr int32_t PARAM_SIZE_SIX = 6; -static NG::PanRecognizer* GetCurrentGestureRecognizer( - napi_env env, napi_callback_info info, size_t* argc = nullptr, napi_value* argv = nullptr) -{ - napi_value thisVar = nullptr; - NAPI_CALL(env, napi_get_cb_info(env, info, argc, argv, &thisVar, nullptr)); - - NG::PanRecognizer* current = nullptr; - napi_unwrap(env, thisVar, (void**)¤t); - CHECK_NULL_RETURN(current, nullptr); - return current; -} - -static napi_value GetTag(napi_env env, napi_callback_info info) -{ - napi_escapable_handle_scope scope = nullptr; - auto status = napi_open_escapable_handle_scope(env, &scope); - if (status != napi_ok) { - return nullptr; - } - NG::PanRecognizer* current = GetCurrentGestureRecognizer(env, info); - if (!current) { - napi_close_escapable_handle_scope(env, scope); - return nullptr; - } - napi_value result = nullptr; - auto gestureInfo = current->GetGestureInfo(); - if (!gestureInfo) { - napi_close_escapable_handle_scope(env, scope); - return nullptr; - } - if (gestureInfo->GetTag().has_value()) { - std::string tag = gestureInfo->GetTag().value(); - napi_create_string_utf8(env, tag.c_str(), NAPI_AUTO_LENGTH, &result); - } else { - napi_get_undefined(env, &result); - } - napi_value newResult = nullptr; - napi_escape_handle(env, scope, result, &newResult); - napi_close_escapable_handle_scope(env, scope); - return newResult; -} - -static napi_value GetType(napi_env env, napi_callback_info info) -{ - napi_escapable_handle_scope scope = nullptr; - auto status = napi_open_escapable_handle_scope(env, &scope); - if (status != napi_ok) { - return nullptr; - } - NG::PanRecognizer* current = GetCurrentGestureRecognizer(env, info); - if (!current) { - napi_close_escapable_handle_scope(env, scope); - return nullptr; - } - napi_value result = nullptr; - auto gestureInfo = current->GetGestureInfo(); - if (!gestureInfo) { - napi_close_escapable_handle_scope(env, scope); - return nullptr; - } - napi_create_int32(env, static_cast(gestureInfo->GetRecognizerType()), &result); - napi_value newResult = nullptr; - napi_escape_handle(env, scope, result, &newResult); - napi_close_escapable_handle_scope(env, scope); - return newResult; -} - -static napi_value IsBuiltIn(napi_env env, napi_callback_info info) -{ - napi_escapable_handle_scope scope = nullptr; - auto status = napi_open_escapable_handle_scope(env, &scope); - if (status != napi_ok) { - return nullptr; - } - NG::PanRecognizer* current = GetCurrentGestureRecognizer(env, info); - if (!current) { - napi_close_escapable_handle_scope(env, scope); - return nullptr; - } - napi_value result = nullptr; - auto gestureInfo = current->GetGestureInfo(); - if (!gestureInfo) { - napi_close_escapable_handle_scope(env, scope); - return nullptr; - } - napi_get_boolean(env, gestureInfo->IsSystemGesture(), &result); - napi_value newResult = nullptr; - napi_escape_handle(env, scope, result, &newResult); - napi_close_escapable_handle_scope(env, scope); - return newResult; -} - -static napi_value SetEnabled(napi_env env, napi_callback_info info) -{ - napi_handle_scope scope = nullptr; - auto status = napi_open_handle_scope(env, &scope); - if (status != napi_ok) { - return nullptr; - } - size_t argc = PARAM_SIZE_ONE; - napi_value argv[PARAM_SIZE_ONE] = { nullptr }; - NG::PanRecognizer* current = GetCurrentGestureRecognizer(env, info, &argc, argv); - if (!current) { - napi_close_handle_scope(env, scope); - return nullptr; - } - napi_valuetype valueType = napi_undefined; - NAPI_CALL(env, napi_typeof(env, argv[PARAM_SIZE_ZERO], &valueType)); - NAPI_ASSERT(env, (valueType == napi_boolean), "Invalid arguments"); - bool isEnabled = false; - napi_get_value_bool(env, argv[PARAM_SIZE_ZERO], &isEnabled); - current->SetEnabled(isEnabled); - napi_close_handle_scope(env, scope); - return nullptr; -} - -static napi_value IsEnabled(napi_env env, napi_callback_info info) -{ - napi_escapable_handle_scope scope = nullptr; - auto status = napi_open_escapable_handle_scope(env, &scope); - if (status != napi_ok) { - return nullptr; - } - NG::PanRecognizer* current = GetCurrentGestureRecognizer(env, info); - if (!current) { - napi_close_escapable_handle_scope(env, scope); - return nullptr; - } - napi_value result = nullptr; - napi_get_boolean(env, current->IsEnabled(), &result); - napi_value newResult = nullptr; - napi_escape_handle(env, scope, result, &newResult); - napi_close_escapable_handle_scope(env, scope); - return newResult; -} - -static napi_value GetState(napi_env env, napi_callback_info info) -{ - napi_escapable_handle_scope scope = nullptr; - auto status = napi_open_escapable_handle_scope(env, &scope); - if (status != napi_ok) { - return nullptr; - } - NG::PanRecognizer* current = GetCurrentGestureRecognizer(env, info); - if (!current) { - napi_close_escapable_handle_scope(env, scope); - return nullptr; - } - napi_value result = nullptr; - napi_create_int32(env, static_cast(current->GetRefereeState()), &result); - napi_value newResult = nullptr; - napi_escape_handle(env, scope, result, &newResult); - napi_close_escapable_handle_scope(env, scope); - return newResult; -} - -static napi_value GetId(napi_env env, napi_callback_info info) -{ - napi_value result = nullptr; - void* data = nullptr; - napi_get_cb_info(env, info, nullptr, nullptr, nullptr, &data); - auto inspectorId = static_cast(data); - CHECK_NULL_RETURN(inspectorId, nullptr); - napi_create_string_utf8(env, (*inspectorId).c_str(), NAPI_AUTO_LENGTH, &result); - return result; -} - -static napi_value GetEventTargetInfo(napi_env env, napi_callback_info info) -{ - napi_escapable_handle_scope scope = nullptr; - auto status = napi_open_escapable_handle_scope(env, &scope); - if (status != napi_ok) { - return nullptr; - } - NG::PanRecognizer* current = GetCurrentGestureRecognizer(env, info); - if (!current) { - napi_close_escapable_handle_scope(env, scope); - return nullptr; - } - napi_value result = nullptr; - napi_create_object(env, &result); - napi_value funcValue = nullptr; - auto attactNode = current->GetAttachedNode().Upgrade(); - if (!attactNode) { - napi_close_escapable_handle_scope(env, scope); - return nullptr; - } - auto inspectorId = std::make_unique(attactNode->GetInspectorIdValue("")); - auto* rawPtr = inspectorId.release(); - status = napi_wrap( - env, result, rawPtr, - [](napi_env env, void* data, void* hint) { - auto origin = static_cast(data); - if (origin) { - delete origin; - } - }, - nullptr, nullptr); - if (status != napi_ok) { - LOGE("napi_wrap failed"); - delete rawPtr; - napi_close_escapable_handle_scope(env, scope); - return nullptr; - } - - napi_create_function(env, GET_ID, 0, GetId, rawPtr, &funcValue); - napi_set_named_property(env, result, GET_ID, funcValue); - napi_value newResult = nullptr; - napi_escape_handle(env, scope, result, &newResult); - napi_close_escapable_handle_scope(env, scope); - return newResult; -} - -static napi_value IsValid(napi_env env, napi_callback_info info) -{ - napi_escapable_handle_scope scope = nullptr; - auto status = napi_open_escapable_handle_scope(env, &scope); - if (status != napi_ok) { - return nullptr; - } - NG::PanRecognizer* current = GetCurrentGestureRecognizer(env, info); - if (!current) { - napi_close_escapable_handle_scope(env, scope); - return nullptr; - } - napi_value result = nullptr; - napi_get_boolean(env, current->IsInResponseLinkRecognizers(), &result); - napi_value newResult = nullptr; - napi_escape_handle(env, scope, result, &newResult); - napi_close_escapable_handle_scope(env, scope); - return newResult; -} - -static napi_value GetFingerCount(napi_env env, napi_callback_info info) -{ - napi_escapable_handle_scope scope = nullptr; - auto status = napi_open_escapable_handle_scope(env, &scope); - if (status != napi_ok) { - return nullptr; - } - NG::PanRecognizer* current = GetCurrentGestureRecognizer(env, info); - if (!current) { - napi_close_escapable_handle_scope(env, scope); - return nullptr; - } - napi_value result = nullptr; - napi_create_int32(env, static_cast(current->GetFingers()), &result); - napi_value newResult = nullptr; - napi_escape_handle(env, scope, result, &newResult); - napi_close_escapable_handle_scope(env, scope); - return newResult; -} - -static napi_value IsFingerCountLimit(napi_env env, napi_callback_info info) -{ - napi_escapable_handle_scope scope = nullptr; - auto status = napi_open_escapable_handle_scope(env, &scope); - if (status != napi_ok) { - return nullptr; - } - NG::PanRecognizer* current = GetCurrentGestureRecognizer(env, info); - if (!current) { - napi_close_escapable_handle_scope(env, scope); - return nullptr; - } - napi_value result = nullptr; - napi_get_boolean(env, current->GetLimitFingerCount(), &result); - napi_value newResult = nullptr; - napi_escape_handle(env, scope, result, &newResult); - napi_close_escapable_handle_scope(env, scope); - return newResult; -} - -struct PanRecognizerWrapper { - NG::PanRecognizer* recognizer; -}; - -static napi_value GetDistance(napi_env env, napi_callback_info info) -{ - double scale = Dimension(1.0, DimensionUnit::VP).ConvertToPx(); - if (NearZero(scale)) { - scale = 1.0; - } - napi_value thisArg; - napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr); - PanRecognizerWrapper* wrapper = nullptr; - napi_unwrap(env, thisArg, reinterpret_cast(&wrapper)); - CHECK_NULL_RETURN(wrapper, nullptr); - auto current = wrapper->recognizer; - CHECK_NULL_RETURN(current, nullptr); - napi_value napiDistance = nullptr; - napi_create_double(env, current->GetDistance() / scale, &napiDistance); - return napiDistance; -} - -static napi_value GetDirection(napi_env env, napi_callback_info info) -{ - napi_value thisArg; - napi_get_cb_info(env, info, nullptr, nullptr, &thisArg, nullptr); - PanRecognizerWrapper* wrapper = nullptr; - napi_unwrap(env, thisArg, reinterpret_cast(&wrapper)); - CHECK_NULL_RETURN(wrapper, nullptr); - auto current = wrapper->recognizer; - CHECK_NULL_RETURN(current, nullptr); - napi_value napiDirection = nullptr; - napi_create_uint32(env, static_cast(current->GetDirection().type), &napiDirection); - return napiDirection; -} - -static napi_value GetPanGestureOptions(napi_env env, napi_callback_info info) -{ - napi_escapable_handle_scope scope = nullptr; - auto status = napi_open_escapable_handle_scope(env, &scope); - if (status != napi_ok) { - return nullptr; - } - NG::PanRecognizer* current = GetCurrentGestureRecognizer(env, info); - if (!current) { - napi_close_escapable_handle_scope(env, scope); - return nullptr; - } - napi_value result = nullptr; - napi_value funcValue = nullptr; - napi_create_object(env, &result); - - PanRecognizerWrapper* wrapper = new PanRecognizerWrapper { current }; - status = napi_wrap( - env, result, wrapper, - [](napi_env env, void* data, void* hint) { - auto castData = reinterpret_cast(data); - if (castData) { - delete castData; - } - }, - nullptr, nullptr); - if (status != napi_ok) { - LOGE("Failed to wrap native object"); - delete wrapper; - napi_close_escapable_handle_scope(env, scope); - return nullptr; - } - - auto setDirection = [](napi_env env, napi_callback_info info) -> napi_value { return nullptr; }; - auto setDistance = [](napi_env env, napi_callback_info info) -> napi_value { return nullptr; }; - auto setFingers = [](napi_env env, napi_callback_info info) -> napi_value { return nullptr; }; - napi_create_function(env, GET_DIRECTION, NAPI_AUTO_LENGTH, GetDirection, nullptr, &funcValue); - napi_set_named_property(env, result, GET_DIRECTION, funcValue); - napi_create_function(env, GET_DISTANCE, NAPI_AUTO_LENGTH, GetDistance, nullptr, &funcValue); - napi_set_named_property(env, result, GET_DISTANCE, funcValue); - napi_create_function(env, SET_DIRECTION, NAPI_AUTO_LENGTH, setDirection, nullptr, &funcValue); - napi_set_named_property(env, result, SET_DIRECTION, funcValue); - napi_create_function(env, SET_DISTANCE, NAPI_AUTO_LENGTH, setDistance, nullptr, &funcValue); - napi_set_named_property(env, result, SET_DISTANCE, funcValue); - napi_create_function(env, SET_FINGERS, NAPI_AUTO_LENGTH, setFingers, nullptr, &funcValue); - napi_set_named_property(env, result, SET_FINGERS, funcValue); - napi_value newResult = nullptr; - napi_escape_handle(env, scope, result, &newResult); - napi_close_escapable_handle_scope(env, scope); - return newResult; -} - bool CheckKeysPressed(const std::vector& pressedKeyCodes, std::vector& checkKeyCodes) { auto hasKeyCode = [pressedKeyCodes](const KeyCode& keyCode) -> bool { @@ -787,19 +409,7 @@ void UIObserverListener::OnWillClick( napi_value objValueFrameNode = nullptr; napi_create_object(env_, &objValueFrameNode); - - auto container = Container::Current(); - if (container == nullptr) { - napi_close_handle_scope(env_, scope); - return; - } - auto frontEnd = container->GetFrontend(); - if (frontEnd == nullptr) { - napi_close_handle_scope(env_, scope); - return; - } - auto nodeId = frameNode->GetId(); - objValueFrameNode = frontEnd->GetFrameNodeValueByNodeId(nodeId); + objValueFrameNode = GetFrameNodeObject(frameNode); napi_value argv[] = { objValueClickEvent, objValueFrameNode }; napi_call_function(env_, nullptr, callback, PARAM_SIZE_TWO, argv, nullptr); @@ -835,19 +445,7 @@ void UIObserverListener::OnDidClick( napi_value objValueFrameNode = nullptr; napi_create_object(env_, &objValueFrameNode); - - auto container = Container::Current(); - if (container == nullptr) { - napi_close_handle_scope(env_, scope); - return; - } - auto frontEnd = container->GetFrontend(); - if (frontEnd == nullptr) { - napi_close_handle_scope(env_, scope); - return; - } - auto nodeId = frameNode->GetId(); - objValueFrameNode = frontEnd->GetFrameNodeValueByNodeId(nodeId); + objValueFrameNode = GetFrameNodeObject(frameNode); napi_value argv[] = { objValueClickEvent, objValueFrameNode }; napi_call_function(env_, nullptr, callback, PARAM_SIZE_TWO, argv, nullptr); @@ -881,26 +479,59 @@ void UIObserverListener::OnPanGestureStateChange(const GestureEvent& gestureEven AddGestureEventInfoThree(objValueGestureEvent, gestureEventInfo); AddGestureEventInfoFour(objValueGestureEvent, gestureEventInfo); AddTargetObject(objValueGestureEvent, gestureEventInfo); - AddGestureRecognizerInfo(objValueGestureRecognizer, current); + GestureObserverListener::AddGestureRecognizerInfo(env_, objValueGestureRecognizer, current); napi_value objValueFrameNode = nullptr; napi_create_object(env_, &objValueFrameNode); + objValueFrameNode = GetFrameNodeObject(frameNode); - auto container = Container::Current(); - if (!container) { - napi_close_handle_scope(env_, scope); + napi_value argv[] = { objValueGestureEvent, objValueGestureRecognizer, objValueFrameNode }; + napi_call_function(env_, nullptr, callback, PARAM_SIZE_THREE, argv, nullptr); + napi_close_handle_scope(env_, scope); +} + +void UIObserverListener::OnGestureStateChange(const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr frameNode, NG::GestureActionPhase phase) +{ + if (!env_ || !callback_ || !current) { + TAG_LOGW( + AceLogTag::ACE_OBSERVER, "Handle gesture change failed, runtime, recognizer or callback function invalid!"); return; } - auto frontEnd = container->GetFrontend(); - if (!frontEnd) { - napi_close_handle_scope(env_, scope); + napi_handle_scope scope = nullptr; + auto status = napi_open_handle_scope(env_, &scope); + if (status != napi_ok) { return; } - auto nodeId = frameNode->GetId(); - objValueFrameNode = frontEnd->GetFrameNodeValueByNodeId(nodeId); - napi_value argv[] = { objValueGestureEvent, objValueGestureRecognizer, objValueFrameNode }; - napi_call_function(env_, nullptr, callback, PARAM_SIZE_THREE, argv, nullptr); + napi_value callback = nullptr; + napi_get_reference_value(env_, callback_, &callback); + + napi_value objValueGestureTriggerInfo = nullptr; + napi_create_object(env_, &objValueGestureTriggerInfo); + napi_value objValueGestureEvent = nullptr; + napi_create_object(env_, &objValueGestureEvent); + napi_value objValueGestureRecognizer = nullptr; + napi_create_object(env_, &objValueGestureRecognizer); + + AddBaseEventInfo(objValueGestureEvent, gestureEventInfo); + AddGestureEventInfoOne(objValueGestureEvent, gestureEventInfo); + AddGestureEventInfoTwo(objValueGestureEvent, gestureEventInfo); + AddGestureEventInfoThree(objValueGestureEvent, gestureEventInfo); + AddGestureEventInfoFour(objValueGestureEvent, gestureEventInfo); + AddTargetObject(objValueGestureEvent, gestureEventInfo); + GestureObserverListener::AddGestureRecognizerInfo(env_, objValueGestureRecognizer, current); + napi_value currentPhase = nullptr; + napi_create_double(env_, static_cast(phase), ¤tPhase); + napi_set_named_property(env_, objValueGestureTriggerInfo, "currentPhase", currentPhase); + napi_set_named_property(env_, objValueGestureTriggerInfo, "event", objValueGestureEvent); + napi_set_named_property(env_, objValueGestureTriggerInfo, "current", objValueGestureRecognizer); + napi_value objValueFrameNode = GetFrameNodeObject(frameNode); + if (objValueFrameNode) { + napi_set_named_property(env_, objValueGestureTriggerInfo, "node", objValueFrameNode); + } + napi_value argv[] = { objValueGestureTriggerInfo }; + napi_call_function(env_, nullptr, callback, PARAM_SIZE_ONE, argv, nullptr); napi_close_handle_scope(env_, scope); } @@ -990,6 +621,7 @@ void UIObserverListener::AddBaseEventInfo(napi_value objValueEvent, const BaseEv napi_value napiPressure = nullptr; napi_value napiTiltX = nullptr; napi_value napiTiltY = nullptr; + napi_value napiRollAngle = nullptr; napi_value napiSourceTool = nullptr; napi_create_double(env_, @@ -1002,6 +634,7 @@ void UIObserverListener::AddBaseEventInfo(napi_value objValueEvent, const BaseEv if (baseEventInfo.GetTiltY().has_value()) { napi_create_double(env_, baseEventInfo.GetTiltY().value(), &napiTiltY); } + napi_create_double(env_, baseEventInfo.GetRollAngle().value_or(0.0f), &napiRollAngle); napi_create_double(env_, static_cast(baseEventInfo.GetSourceTool()), &napiSourceTool); napi_set_named_property(env_, objValueEvent, "timestamp", napiTimeStamp); @@ -1009,6 +642,7 @@ void UIObserverListener::AddBaseEventInfo(napi_value objValueEvent, const BaseEv napi_set_named_property(env_, objValueEvent, "pressure", napiPressure); napi_set_named_property(env_, objValueEvent, "tiltX", napiTiltX); napi_set_named_property(env_, objValueEvent, "tiltY", napiTiltY); + napi_set_named_property(env_, objValueEvent, "rollAngle", napiRollAngle); napi_set_named_property(env_, objValueEvent, "sourceTool", napiSourceTool); napi_close_handle_scope(env_, scope); @@ -1391,57 +1025,6 @@ void UIObserverListener::AddGestureEventInfoFour(napi_value objValueEvent, const napi_close_handle_scope(env_, scope); } -void UIObserverListener::AddGestureRecognizerInfo( - napi_value objValueGestureRecognizer, const RefPtr& current) -{ - napi_handle_scope scope = nullptr; - auto status = napi_open_handle_scope(env_, &scope); - if (status != napi_ok) { - return; - } - current->IncRefCount(); - status = napi_wrap( - env_, objValueGestureRecognizer, AceType::RawPtr(current), - [](napi_env env, void* data, void* hint) { - NG::PanRecognizer* current = reinterpret_cast(data); - if (current != nullptr) { - current->DecRefCount(); - } - }, - nullptr, nullptr); - if (status != napi_ok) { - LOGE("napi_wrap failed"); - current->DecRefCount(); - napi_close_handle_scope(env_, scope); - return; - } - - napi_value funcValue = nullptr; - napi_create_function(env_, GET_TAG, 0, GetTag, nullptr, &funcValue); - napi_set_named_property(env_, objValueGestureRecognizer, GET_TAG, funcValue); - napi_create_function(env_, GET_TYPE, 0, GetType, nullptr, &funcValue); - napi_set_named_property(env_, objValueGestureRecognizer, GET_TYPE, funcValue); - napi_create_function(env_, IS_BUILT_IN, 0, IsBuiltIn, nullptr, &funcValue); - napi_set_named_property(env_, objValueGestureRecognizer, IS_BUILT_IN, funcValue); - napi_create_function(env_, SET_ENABLED, 0, SetEnabled, nullptr, &funcValue); - napi_set_named_property(env_, objValueGestureRecognizer, SET_ENABLED, funcValue); - napi_create_function(env_, IS_ENABLED, 0, IsEnabled, nullptr, &funcValue); - napi_set_named_property(env_, objValueGestureRecognizer, IS_ENABLED, funcValue); - napi_create_function(env_, GET_STATE, 0, GetState, nullptr, &funcValue); - napi_set_named_property(env_, objValueGestureRecognizer, GET_STATE, funcValue); - napi_create_function(env_, GET_EVENT_TARGET_INFO, 0, GetEventTargetInfo, nullptr, &funcValue); - napi_set_named_property(env_, objValueGestureRecognizer, GET_EVENT_TARGET_INFO, funcValue); - napi_create_function(env_, IS_VALID, 0, IsValid, nullptr, &funcValue); - napi_set_named_property(env_, objValueGestureRecognizer, IS_VALID, funcValue); - napi_create_function(env_, GET_FINGER_COUNT, 0, GetFingerCount, nullptr, &funcValue); - napi_set_named_property(env_, objValueGestureRecognizer, GET_FINGER_COUNT, funcValue); - napi_create_function(env_, IS_FINGER_COUNT_LIMIT, 0, IsFingerCountLimit, nullptr, &funcValue); - napi_set_named_property(env_, objValueGestureRecognizer, IS_FINGER_COUNT_LIMIT, funcValue); - napi_create_function(env_, GET_PANGESTURE_OPTIONS, 0, GetPanGestureOptions, nullptr, &funcValue); - napi_set_named_property(env_, objValueGestureRecognizer, GET_PANGESTURE_OPTIONS, funcValue); - napi_close_handle_scope(env_, scope); -} - void UIObserverListener::AddTargetObject(napi_value objValueEvent, const BaseEventInfo& baseEventInfo) { napi_handle_scope scope = nullptr; @@ -1532,6 +1115,18 @@ napi_value UIObserverListener::GetNapiCallback() return callback; } +napi_value UIObserverListener::GetFrameNodeObject(const RefPtr& frameNode) +{ + CHECK_NULL_RETURN(frameNode, nullptr); + auto container = Container::Current(); + CHECK_NULL_RETURN(frameNode, nullptr); + + auto frontEnd = container->GetFrontend(); + CHECK_NULL_RETURN(frameNode, nullptr); + + return frontEnd->GetFrameNodeValueByNodeId(frameNode->GetId()); +} + bool UIObserverListener::NapiEqual(napi_value cb) { bool isEquals = false; diff --git a/interfaces/napi/kits/observer/ui_observer_listener.h b/interfaces/napi/kits/observer/ui_observer_listener.h index 22f6b86e9c22c0e402b181d29dac7ab6f316b3f3..be5b042271452eaef0c76721c1c14a1d5a94d84a 100644 --- a/interfaces/napi/kits/observer/ui_observer_listener.h +++ b/interfaces/napi/kits/observer/ui_observer_listener.h @@ -50,6 +50,8 @@ public: const RefPtr frameNode); void OnPanGestureStateChange(const GestureEvent& gestureEventInfo, const RefPtr& current, const RefPtr frameNode); + void OnGestureStateChange(const GestureEvent& gestureEventInfo, const RefPtr& current, + const RefPtr frameNode, NG::GestureActionPhase phase); void OnTabContentStateChange(const NG::TabContentInfo& tabContentInfo); void OnNodeRenderStateChange(NG::FrameNode* frameNode, NG::NodeRenderState nodeRenderState); void OnNavDestinationSwitch(const NG::NavDestinationSwitchInfo& switchInfo); @@ -60,6 +62,7 @@ private: napi_value CreateNavDestinationSwitchInfoObj(const NG::NavDestinationSwitchInfo& switchInfo); napi_value CreateNavDestinationInfoObj(const NG::NavDestinationInfo& info); napi_value GetNapiCallback(); + napi_value GetFrameNodeObject(const RefPtr& frameNode); static napi_valuetype GetValueType(napi_env env, napi_value value); static napi_value GetNamedProperty(napi_env env, napi_value object, const std::string& propertyName); void AddBaseEventInfo(napi_value objValueEvent, const BaseEventInfo& baseEventInfo); @@ -73,7 +76,6 @@ private: void AddClickEventInfoOne(napi_value objValueClickEvent, const ClickInfo& clickInfo); void AddClickEventInfoTwo(napi_value objValueClickEvent, const ClickInfo& clickInfo); void AddFingerObjectInfo(napi_value napiFinger, const FingerInfo& finger); - void AddGestureRecognizerInfo(napi_value objValueGestureRecognizer, const RefPtr& current); void AddTargetObject(napi_value objValueEvent, const BaseEventInfo& baseEventInfo); napi_env env_ = nullptr; napi_ref callback_ = nullptr; diff --git a/test/unittest/core/gestures/gesture_recognizer_test_ng.cpp b/test/unittest/core/gestures/gesture_recognizer_test_ng.cpp index d6b6e4ec44a0d2afe3611db69dc745ce5470d351..0564e151f9f0ed9b2c931888042f5705fba2dd00 100644 --- a/test/unittest/core/gestures/gesture_recognizer_test_ng.cpp +++ b/test/unittest/core/gestures/gesture_recognizer_test_ng.cpp @@ -691,4 +691,311 @@ HWTEST_F(GestureRecognizerTestNg, LongPressGestureJudgeTest001, TestSize.Level1) auto result = longPressRecognizerPtr->TriggerGestureJudgeCallback(); EXPECT_EQ(result, GestureJudgeResult::REJECT); } + +/** + * @tc.name: HandleGestureAcceptTest001 + * @tc.desc: Test function: HandleGestureAccept for PanRecognizer + * @tc.type: FUNC + */ +HWTEST_F(GestureRecognizerTestNg, HandleGestureAcceptTest001, TestSize.Level1) +{ + auto frameNode = FrameNode::CreateFrameNode("myButton", 0, AceType::MakeRefPtr()); + ASSERT_NE(frameNode, nullptr); + PanDirection direction; + RefPtr panRecognizerPtr = AceType::MakeRefPtr(SINGLE_FINGER_NUMBER, direction, 0); + ASSERT_NE(panRecognizerPtr, nullptr); + panRecognizerPtr->AttachFrameNode(frameNode); + GestureEvent info; + auto start = [](GestureEvent& info) {}; + auto action = [](GestureEvent& info) {}; + auto end = [](GestureEvent& info) {}; + panRecognizerPtr->SetOnActionStart(start); + panRecognizerPtr->SetOnAction(action); + panRecognizerPtr->SetOnActionEnd(end); + panRecognizerPtr->SetRecognizerType(GestureTypeName::PAN_GESTURE); + auto startCallback = [](GestureListenerType gestureListenerType, const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr& frameNode, + GestureActionPhase phase) { + EXPECT_EQ(phase, GestureActionPhase::WILL_START); + EXPECT_EQ(gestureListenerType, GestureListenerType::PAN); + }; + UIObserverHandler::GetInstance().SetHandleGestureHandleFunc(startCallback); + panRecognizerPtr->SendCallbackMsg(panRecognizerPtr->onActionStart_, GestureCallbackType::START); + auto actionCallback = [](GestureListenerType gestureListenerType, const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr& frameNode, + GestureActionPhase phase) { + EXPECT_EQ(phase, GestureActionPhase::UNKNOWN); + EXPECT_EQ(gestureListenerType, GestureListenerType::PAN); + }; + UIObserverHandler::GetInstance().SetHandleGestureHandleFunc(actionCallback); + panRecognizerPtr->SendCallbackMsg(panRecognizerPtr->onAction_, GestureCallbackType::ACTION); + auto endCallback = [](GestureListenerType gestureListenerType, const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr& frameNode, + GestureActionPhase phase) { + EXPECT_EQ(phase, GestureActionPhase::WILL_END); + EXPECT_EQ(gestureListenerType, GestureListenerType::PAN); + }; + UIObserverHandler::GetInstance().SetHandleGestureHandleFunc(endCallback); + panRecognizerPtr->SendCallbackMsg(panRecognizerPtr->onActionEnd_, GestureCallbackType::END); + auto endCallbackError = [](GestureListenerType gestureListenerType, const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr& frameNode, + GestureActionPhase phase) { + EXPECT_EQ(phase, GestureActionPhase::UNKNOWN); + EXPECT_EQ(gestureListenerType, GestureListenerType::PAN); + }; + UIObserverHandler::GetInstance().SetHandleGestureHandleFunc(endCallbackError); + panRecognizerPtr->SendCallbackMsg(panRecognizerPtr->onActionEnd_, GestureCallbackType::UPDATE); +} + +/** + * @tc.name: HandleGestureAcceptTest002 + * @tc.desc: Test function: HandleGestureAccept for ClickRecognizer + * @tc.type: FUNC + */ +HWTEST_F(GestureRecognizerTestNg, HandleGestureAcceptTest002, TestSize.Level1) +{ + auto frameNode = FrameNode::CreateFrameNode("myButton", 0, AceType::MakeRefPtr()); + ASSERT_NE(frameNode, nullptr); + RefPtr clickRecognizerPtr = AceType::MakeRefPtr(FINGER_NUMBER, COUNT); + ASSERT_NE(clickRecognizerPtr, nullptr); + clickRecognizerPtr->AttachFrameNode(frameNode); + GestureEvent info; + auto start = [](GestureEvent& info) {}; + auto action = [](GestureEvent& info) {}; + auto end = [](GestureEvent& info) {}; + clickRecognizerPtr->SetOnActionStart(start); + clickRecognizerPtr->SetOnAction(action); + clickRecognizerPtr->SetOnActionEnd(end); + clickRecognizerPtr->SetRecognizerType(GestureTypeName::TAP_GESTURE); + + auto startCallback = [](GestureListenerType gestureListenerType, const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr& frameNode, + GestureActionPhase phase) { + EXPECT_EQ(phase, GestureActionPhase::UNKNOWN); + EXPECT_EQ(gestureListenerType, GestureListenerType::TAP); + }; + UIObserverHandler::GetInstance().SetHandleGestureHandleFunc(startCallback); + clickRecognizerPtr->SendCallbackMsg(clickRecognizerPtr->onActionStart_, GestureCallbackType::START); + + auto actionCallback = [](GestureListenerType gestureListenerType, const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr& frameNode, + GestureActionPhase phase) { + EXPECT_EQ(phase, GestureActionPhase::WILL_START); + EXPECT_EQ(gestureListenerType, GestureListenerType::TAP); + }; + UIObserverHandler::GetInstance().SetHandleGestureHandleFunc(actionCallback); + clickRecognizerPtr->SendCallbackMsg(clickRecognizerPtr->onAction_, GestureCallbackType::ACTION); + + auto endCallback = [](GestureListenerType gestureListenerType, const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr& frameNode, + GestureActionPhase phase) { + EXPECT_EQ(phase, GestureActionPhase::UNKNOWN); + EXPECT_EQ(gestureListenerType, GestureListenerType::TAP); + }; + UIObserverHandler::GetInstance().SetHandleGestureHandleFunc(endCallback); + clickRecognizerPtr->SendCallbackMsg(clickRecognizerPtr->onActionEnd_, GestureCallbackType::END); + clickRecognizerPtr->SetRecognizerType(GestureTypeName::CLICK); + clickRecognizerPtr->SendCallbackMsg(clickRecognizerPtr->onActionEnd_, GestureCallbackType::END); +} + +/** + * @tc.name: HandleGestureAcceptTest003 + * @tc.desc: Test function: HandleGestureAccept for LongPressRecognizer + * @tc.type: FUNC + */ +HWTEST_F(GestureRecognizerTestNg, HandleGestureAcceptTest003, TestSize.Level1) +{ + auto frameNode = FrameNode::CreateFrameNode("myButton", 0, AceType::MakeRefPtr()); + ASSERT_NE(frameNode, nullptr); + RefPtr longPressRecognizerPtr = AceType::MakeRefPtr(LONG_PRESS_DURATION, + FINGER_NUMBER, false); + ASSERT_NE(longPressRecognizerPtr, nullptr); + longPressRecognizerPtr->AttachFrameNode(frameNode); + GestureEvent info; + auto start = [](GestureEvent& info) {}; + auto action = [](GestureEvent& info) {}; + auto end = [](GestureEvent& info) {}; + longPressRecognizerPtr->SetOnActionStart(start); + longPressRecognizerPtr->SetOnAction(action); + longPressRecognizerPtr->SetOnActionEnd(end); + longPressRecognizerPtr->SetRecognizerType(GestureTypeName::LONG_PRESS_GESTURE); + + auto startCallback = [](GestureListenerType gestureListenerType, const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr& frameNode, + GestureActionPhase phase) { + EXPECT_EQ(phase, GestureActionPhase::WILL_START); + EXPECT_EQ(gestureListenerType, GestureListenerType::LONG_PRESS); + }; + UIObserverHandler::GetInstance().SetHandleGestureHandleFunc(startCallback); + longPressRecognizerPtr->SendCallbackMsg(longPressRecognizerPtr->onActionStart_, false, GestureCallbackType::START); + + auto actionCallback = [](GestureListenerType gestureListenerType, const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr& frameNode, + GestureActionPhase phase) { + EXPECT_EQ(phase, GestureActionPhase::UNKNOWN); + EXPECT_EQ(gestureListenerType, GestureListenerType::LONG_PRESS); + }; + UIObserverHandler::GetInstance().SetHandleGestureHandleFunc(actionCallback); + longPressRecognizerPtr->SendCallbackMsg(longPressRecognizerPtr->onAction_, false, GestureCallbackType::ACTION); + + auto endCallback = [](GestureListenerType gestureListenerType, const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr& frameNode, + GestureActionPhase phase) { + EXPECT_EQ(phase, GestureActionPhase::WILL_END); + EXPECT_EQ(gestureListenerType, GestureListenerType::LONG_PRESS); + }; + UIObserverHandler::GetInstance().SetHandleGestureHandleFunc(endCallback); + longPressRecognizerPtr->SendCallbackMsg(longPressRecognizerPtr->onActionEnd_, false, GestureCallbackType::END); +} + +/** + * @tc.name: HandleGestureAcceptTest004 + * @tc.desc: Test function: HandleGestureAccept for PinchRecognizer + * @tc.type: FUNC + */ +HWTEST_F(GestureRecognizerTestNg, HandleGestureAcceptTest004, TestSize.Level1) +{ + auto frameNode = FrameNode::CreateFrameNode("myButton", 0, AceType::MakeRefPtr()); + ASSERT_NE(frameNode, nullptr); + RefPtr pinchRecognizerPtr = AceType::MakeRefPtr(SINGLE_FINGER_NUMBER, + PINCH_GESTURE_DISTANCE); + ASSERT_NE(pinchRecognizerPtr, nullptr); + pinchRecognizerPtr->AttachFrameNode(frameNode); + GestureEvent info; + auto start = [](GestureEvent& info) {}; + auto action = [](GestureEvent& info) {}; + auto end = [](GestureEvent& info) {}; + pinchRecognizerPtr->SetOnActionStart(start); + pinchRecognizerPtr->SetOnAction(action); + pinchRecognizerPtr->SetOnActionEnd(end); + pinchRecognizerPtr->SetRecognizerType(GestureTypeName::PINCH_GESTURE); + + auto startCallback = [](GestureListenerType gestureListenerType, const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr& frameNode, + GestureActionPhase phase) { + EXPECT_EQ(phase, GestureActionPhase::WILL_START); + EXPECT_EQ(gestureListenerType, GestureListenerType::PINCH); + }; + UIObserverHandler::GetInstance().SetHandleGestureHandleFunc(startCallback); + pinchRecognizerPtr->SendCallbackMsg(pinchRecognizerPtr->onActionStart_, GestureCallbackType::START); + + auto actionCallback = [](GestureListenerType gestureListenerType, const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr& frameNode, + GestureActionPhase phase) { + EXPECT_EQ(phase, GestureActionPhase::UNKNOWN); + EXPECT_EQ(gestureListenerType, GestureListenerType::PINCH); + }; + UIObserverHandler::GetInstance().SetHandleGestureHandleFunc(actionCallback); + pinchRecognizerPtr->SendCallbackMsg(pinchRecognizerPtr->onAction_, GestureCallbackType::ACTION); + + auto endCallback = [](GestureListenerType gestureListenerType, const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr& frameNode, + GestureActionPhase phase) { + EXPECT_EQ(phase, GestureActionPhase::WILL_END); + EXPECT_EQ(gestureListenerType, GestureListenerType::PINCH); + }; + UIObserverHandler::GetInstance().SetHandleGestureHandleFunc(endCallback); + pinchRecognizerPtr->SendCallbackMsg(pinchRecognizerPtr->onActionEnd_, GestureCallbackType::END); +} + +/** + * @tc.name: HandleGestureAcceptTest005 + * @tc.desc: Test function: HandleGestureAccept for RotationRecognizer + * @tc.type: FUNC + */ +HWTEST_F(GestureRecognizerTestNg, HandleGestureAcceptTest005, TestSize.Level1) +{ + auto frameNode = FrameNode::CreateFrameNode("myButton", 0, AceType::MakeRefPtr()); + ASSERT_NE(frameNode, nullptr); + RefPtr rotationRecognizerPtr = + AceType::MakeRefPtr(SINGLE_FINGER_NUMBER, ROTATION_GESTURE_ANGLE); + ASSERT_NE(rotationRecognizerPtr, nullptr); + rotationRecognizerPtr->AttachFrameNode(frameNode); + GestureEvent info; + auto start = [](GestureEvent& info) {}; + auto action = [](GestureEvent& info) {}; + auto end = [](GestureEvent& info) {}; + rotationRecognizerPtr->SetOnActionStart(start); + rotationRecognizerPtr->SetOnAction(action); + rotationRecognizerPtr->SetOnActionEnd(end); + rotationRecognizerPtr->SetRecognizerType(GestureTypeName::ROTATION_GESTURE); + + auto startCallback = [](GestureListenerType gestureListenerType, const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr& frameNode, + GestureActionPhase phase) { + EXPECT_EQ(phase, GestureActionPhase::WILL_START); + EXPECT_EQ(gestureListenerType, GestureListenerType::ROTATION); + }; + UIObserverHandler::GetInstance().SetHandleGestureHandleFunc(startCallback); + rotationRecognizerPtr->SendCallbackMsg(rotationRecognizerPtr->onActionStart_, GestureCallbackType::START); + + auto actionCallback = [](GestureListenerType gestureListenerType, const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr& frameNode, + GestureActionPhase phase) { + EXPECT_EQ(phase, GestureActionPhase::UNKNOWN); + EXPECT_EQ(gestureListenerType, GestureListenerType::ROTATION); + }; + UIObserverHandler::GetInstance().SetHandleGestureHandleFunc(actionCallback); + rotationRecognizerPtr->SendCallbackMsg(rotationRecognizerPtr->onAction_, GestureCallbackType::ACTION); + + auto endCallback = [](GestureListenerType gestureListenerType, const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr& frameNode, + GestureActionPhase phase) { + EXPECT_EQ(phase, GestureActionPhase::WILL_END); + EXPECT_EQ(gestureListenerType, GestureListenerType::ROTATION); + }; + UIObserverHandler::GetInstance().SetHandleGestureHandleFunc(endCallback); + rotationRecognizerPtr->SendCallbackMsg(rotationRecognizerPtr->onActionEnd_, GestureCallbackType::END); +} + +/** + * @tc.name: HandleGestureAcceptTest006 + * @tc.desc: Test function: HandleGestureAccept for SwipeRecognizer + * @tc.type: FUNC + */ +HWTEST_F(GestureRecognizerTestNg, HandleGestureAcceptTest006, TestSize.Level1) +{ + auto frameNode = FrameNode::CreateFrameNode("myButton", 0, AceType::MakeRefPtr()); + ASSERT_NE(frameNode, nullptr); + SwipeDirection swipeDirection; + RefPtr swipeRecognizerPtr = + AceType::MakeRefPtr(SINGLE_FINGER_NUMBER, swipeDirection, SWIPE_SPEED); + ASSERT_NE(swipeRecognizerPtr, nullptr); + swipeRecognizerPtr->AttachFrameNode(frameNode); + GestureEvent info; + auto start = [](GestureEvent& info) {}; + auto action = [](GestureEvent& info) {}; + auto end = [](GestureEvent& info) {}; + swipeRecognizerPtr->SetOnActionStart(start); + swipeRecognizerPtr->SetOnAction(action); + swipeRecognizerPtr->SetOnActionEnd(end); + swipeRecognizerPtr->SetRecognizerType(GestureTypeName::SWIPE_GESTURE); + + auto startCallback = [](GestureListenerType gestureListenerType, const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr& frameNode, + GestureActionPhase phase) { + EXPECT_EQ(phase, GestureActionPhase::UNKNOWN); + EXPECT_EQ(gestureListenerType, GestureListenerType::SWIPE); + }; + UIObserverHandler::GetInstance().SetHandleGestureHandleFunc(startCallback); + swipeRecognizerPtr->SendCallbackMsg(swipeRecognizerPtr->onActionStart_, GestureCallbackType::START); + + auto actionCallback = [](GestureListenerType gestureListenerType, const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr& frameNode, + GestureActionPhase phase) { + EXPECT_EQ(phase, GestureActionPhase::WILL_START); + EXPECT_EQ(gestureListenerType, GestureListenerType::SWIPE); + }; + UIObserverHandler::GetInstance().SetHandleGestureHandleFunc(actionCallback); + swipeRecognizerPtr->SendCallbackMsg(swipeRecognizerPtr->onAction_, GestureCallbackType::ACTION); + + auto endCallback = [](GestureListenerType gestureListenerType, const GestureEvent& gestureEventInfo, + const RefPtr& current, const RefPtr& frameNode, + GestureActionPhase phase) { + EXPECT_EQ(phase, GestureActionPhase::UNKNOWN); + EXPECT_EQ(gestureListenerType, GestureListenerType::SWIPE); + }; + UIObserverHandler::GetInstance().SetHandleGestureHandleFunc(endCallback); + swipeRecognizerPtr->SendCallbackMsg(swipeRecognizerPtr->onActionEnd_, GestureCallbackType::END); +} } // namespace OHOS::Ace::NG \ No newline at end of file