• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2023 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "frameworks/bridge/declarative_frontend/engine/functions/js_gesture_judge_function.h"
17 
18 #include "base/memory/ace_type.h"
19 #include "base/utils/utils.h"
20 #include "bridge/declarative_frontend/engine/functions/js_should_built_in_recognizer_parallel_with_function.h"
21 #include "core/components/common/layout/constants.h"
22 #include "core/components_ng/gestures/base_gesture_event.h"
23 #include "frameworks/bridge/declarative_frontend/engine/jsi/nativeModule/arkts_utils.h"
24 
25 namespace OHOS::Ace::Framework {
26 constexpr int32_t PARAM_COUNT_THREE = 3;
27 constexpr int32_t PARAM_COUNT_FOUR = 4;
28 
Execute(const RefPtr<NG::GestureInfo> & gestureInfo,const std::shared_ptr<BaseGestureEvent> & info)29 GestureJudgeResult JsGestureJudgeFunction::Execute(
30     const RefPtr<NG::GestureInfo>& gestureInfo, const std::shared_ptr<BaseGestureEvent>& info)
31 {
32     JSRef<JSObject> gestureInfoObj = JSRef<JSObject>::New();
33     CHECK_NULL_RETURN(gestureInfo, GestureJudgeResult::CONTINUE);
34     CHECK_NULL_RETURN(info, GestureJudgeResult::CONTINUE);
35     if (gestureInfo->GetTag().has_value()) {
36         gestureInfoObj->SetProperty<std::string>("tag", gestureInfo->GetTag().value());
37     }
38     gestureInfoObj->SetProperty<int32_t>("type", static_cast<int32_t>(gestureInfo->GetType()));
39     gestureInfoObj->SetProperty<bool>("isSystemGesture", gestureInfo->IsSystemGesture());
40     gestureInfoObj->SetProperty<int32_t>("targetDisplayId", info->GetTargetDisplayId());
41     auto obj = CreateGestureEventObject(info, gestureInfo->GetType());
42     int32_t paramCount = 2;
43     JSRef<JSVal> params[paramCount];
44     params[0] = gestureInfoObj;
45     params[1] = obj;
46     auto jsValue = JsFunction::ExecuteJS(paramCount, params);
47     auto returnValue = GestureJudgeResult::CONTINUE;
48     if (jsValue->IsNumber()) {
49         returnValue = static_cast<GestureJudgeResult>(jsValue->ToNumber<int32_t>());
50     }
51     return returnValue;
52 }
53 
Execute(const std::shared_ptr<BaseGestureEvent> & info,const RefPtr<NG::NGGestureRecognizer> & current,const std::list<RefPtr<NG::NGGestureRecognizer>> & others)54 GestureJudgeResult JsGestureJudgeFunction::Execute(const std::shared_ptr<BaseGestureEvent>& info,
55     const RefPtr<NG::NGGestureRecognizer>& current, const std::list<RefPtr<NG::NGGestureRecognizer>>& others)
56 {
57     CHECK_NULL_RETURN(info, GestureJudgeResult::CONTINUE);
58     auto gestureInfo = current->GetGestureInfo();
59     CHECK_NULL_RETURN(gestureInfo, GestureJudgeResult::CONTINUE);
60     auto obj = CreateGestureEventObject(info, gestureInfo->GetRecognizerType());
61     JSRef<JSVal> params[PARAM_COUNT_FOUR];
62     params[0] = obj;
63     auto currentObj = JsShouldBuiltInRecognizerParallelWithFunction::CreateRecognizerObject(current);
64     params[1] = currentObj;
65     JSRef<JSArray> othersArr = JSRef<JSArray>::New();
66     uint32_t othersIdx = 0;
67     for (const auto& item : others) {
68         auto othersObj = JsShouldBuiltInRecognizerParallelWithFunction::CreateRecognizerObject(item);
69         othersArr->SetValueAt(othersIdx++, othersObj);
70     }
71 
72     auto touchRecognizerMap = CreateTouchRecognizerMap(info, current);
73     JSRef<JSArray> touchRecognizers = JSRef<JSArray>::New();
74     uint32_t touchRecognizersIdx = 0;
75     for (auto& [item, fingerIds] : touchRecognizerMap) {
76         JSRef<JSObject> recognizerObj = JSClass<JSTouchRecognizer>::NewInstance();
77         auto jsRecognizer = Referenced::Claim(recognizerObj->Unwrap<JSTouchRecognizer>());
78         if (jsRecognizer) {
79             jsRecognizer->SetTouchData(item, fingerIds);
80         }
81         touchRecognizers->SetValueAt(touchRecognizersIdx++, recognizerObj);
82     }
83     params[2] = othersArr;
84     params[PARAM_COUNT_THREE] = touchRecognizers;
85     auto jsValue = JsFunction::ExecuteJS(PARAM_COUNT_FOUR, params);
86     auto returnValue = GestureJudgeResult::CONTINUE;
87     if (jsValue->IsNumber()) {
88         returnValue = static_cast<GestureJudgeResult>(jsValue->ToNumber<int32_t>());
89     }
90     return returnValue;
91 }
92 
CreateTouchRecognizerMap(const std::shared_ptr<BaseGestureEvent> & info,const RefPtr<NG::NGGestureRecognizer> & current)93 TouchRecognizerMap JsGestureJudgeFunction::CreateTouchRecognizerMap(
94     const std::shared_ptr<BaseGestureEvent>& info, const RefPtr<NG::NGGestureRecognizer>& current)
95 {
96     TouchRecognizerMap touchRecognizerMap;
97     auto frameNode = current->GetAttachedNode().Upgrade();
98     CHECK_NULL_RETURN(frameNode, touchRecognizerMap);
99     auto pipeline = frameNode->GetContext();
100     CHECK_NULL_RETURN(pipeline, touchRecognizerMap);
101     auto eventManager = pipeline->GetEventManager();
102     CHECK_NULL_RETURN(eventManager, touchRecognizerMap);
103     auto& touchTestResult = eventManager->touchTestResults_;
104     const auto& fingerList = info->GetFingerList();
105     for (const auto& finger : fingerList) {
106         auto& touchTargetList = touchTestResult[finger.fingerId_];
107         CollectTouchEventTarget(touchRecognizerMap, touchTargetList, AceType::RawPtr(frameNode), finger.fingerId_);
108     }
109     return touchRecognizerMap;
110 }
111 
CollectTouchEventTarget(TouchRecognizerMap & dict,std::list<RefPtr<TouchEventTarget>> & targets,NG::FrameNode * frameNode,int32_t fingerId)112 void JsGestureJudgeFunction::CollectTouchEventTarget(
113     TouchRecognizerMap& dict, std::list<RefPtr<TouchEventTarget>>& targets, NG::FrameNode* frameNode, int32_t fingerId)
114 {
115     for (auto& target : targets) {
116         if (AceType::DynamicCast<NG::NGGestureRecognizer>(target)) {
117             continue;
118         }
119         auto weakTarget = WeakPtr<TouchEventTarget>(target);
120         if (dict.find(weakTarget) != dict.end() && dict[weakTarget].count(fingerId) > 0) {
121             continue;
122         }
123         auto targetNode = target->GetAttachedNode().Upgrade();
124         if (targetNode && targetNode == frameNode) {
125             dict[weakTarget].insert(fingerId);
126             return;
127         }
128         while (targetNode) {
129             if (targetNode == frameNode) {
130                 dict[weakTarget].insert(fingerId);
131                 break;
132             }
133             targetNode = targetNode->GetParentFrameNode();
134         }
135     }
136 }
137 
CreateFingerInfo(const FingerInfo & fingerInfo)138 JSRef<JSObject> JsGestureJudgeFunction::CreateFingerInfo(const FingerInfo& fingerInfo)
139 {
140     JSRef<JSObject> fingerInfoObj = JSRef<JSObject>::New();
141     const OHOS::Ace::Offset& globalLocation = fingerInfo.globalLocation_;
142     const OHOS::Ace::Offset& localLocation = fingerInfo.localLocation_;
143     const OHOS::Ace::Offset& screenLocation = fingerInfo.screenLocation_;
144     const OHOS::Ace::Offset& globalDisplayLocation = fingerInfo.globalDisplayLocation_;
145     fingerInfoObj->SetProperty<int32_t>("id", fingerInfo.fingerId_);
146     fingerInfoObj->SetProperty<int32_t>("hand", fingerInfo.operatingHand_);
147     fingerInfoObj->SetProperty<double>("globalX", PipelineBase::Px2VpWithCurrentDensity(globalLocation.GetX()));
148     fingerInfoObj->SetProperty<double>("globalY", PipelineBase::Px2VpWithCurrentDensity(globalLocation.GetY()));
149     fingerInfoObj->SetProperty<double>("localX", PipelineBase::Px2VpWithCurrentDensity(localLocation.GetX()));
150     fingerInfoObj->SetProperty<double>("localY", PipelineBase::Px2VpWithCurrentDensity(localLocation.GetY()));
151     fingerInfoObj->SetProperty<double>("displayX", PipelineBase::Px2VpWithCurrentDensity(screenLocation.GetX()));
152     fingerInfoObj->SetProperty<double>("displayY", PipelineBase::Px2VpWithCurrentDensity(screenLocation.GetY()));
153     fingerInfoObj->SetProperty<double>(
154         "globalDisplayX", PipelineBase::Px2VpWithCurrentDensity(globalDisplayLocation.GetX()));
155     fingerInfoObj->SetProperty<double>(
156         "globalDisplayY", PipelineBase::Px2VpWithCurrentDensity(globalDisplayLocation.GetY()));
157     return fingerInfoObj;
158 }
159 
CreateEventTargetObject(const std::shared_ptr<BaseGestureEvent> & info)160 JSRef<JSObject> JsGestureJudgeFunction::CreateEventTargetObject(const std::shared_ptr<BaseGestureEvent>& info)
161 {
162     JSRef<JSObjTemplate> objectTemplate = JSRef<JSObjTemplate>::New();
163     JSRef<JSObject> target = objectTemplate->NewInstance();
164     JSRef<JSObject> area = objectTemplate->NewInstance();
165     JSRef<JSObject> offset = objectTemplate->NewInstance();
166     JSRef<JSObject> globalOffset = objectTemplate->NewInstance();
167     const auto& localOffset = info->GetTarget().area.GetOffset();
168     const auto& origin = info->GetTarget().origin;
169     offset->SetProperty<double>("x", localOffset.GetX().ConvertToVp());
170     offset->SetProperty<double>("y", localOffset.GetY().ConvertToVp());
171     globalOffset->SetProperty<double>("x", (origin.GetX().ConvertToVp() + localOffset.GetX().ConvertToVp()));
172     globalOffset->SetProperty<double>("y", (origin.GetY().ConvertToVp() + localOffset.GetY().ConvertToVp()));
173     area->SetPropertyObject("position", offset);
174     area->SetPropertyObject("globalPosition", globalOffset);
175     area->SetProperty<double>("width", info->GetTarget().area.GetWidth().ConvertToVp());
176     area->SetProperty<double>("height", info->GetTarget().area.GetHeight().ConvertToVp());
177     target->SetPropertyObject("area", area);
178     if (!info->GetTarget().id.empty()) {
179         target->SetProperty<const char*>("id", info->GetTarget().id.c_str());
180     } else {
181         target->SetPropertyObject("id", JsiValue::Undefined());
182     }
183     return target;
184 }
185 
ParsePanGestureEvent(JSRef<JSObject> & obj,const std::shared_ptr<BaseGestureEvent> & info)186 void JsGestureJudgeFunction::ParsePanGestureEvent(JSRef<JSObject>& obj, const std::shared_ptr<BaseGestureEvent>& info)
187 {
188     auto panGestureEvent = TypeInfoHelper::DynamicCast<PanGestureEvent>(info.get());
189     if (panGestureEvent) {
190         obj->SetProperty<double>(
191             "offsetX", PipelineBase::Px2VpWithCurrentDensity(panGestureEvent->GetOffsetX()));
192         obj->SetProperty<double>(
193             "offsetY", PipelineBase::Px2VpWithCurrentDensity(panGestureEvent->GetOffsetY()));
194         obj->SetProperty<double>(
195             "velocityX", PipelineBase::Px2VpWithCurrentDensity(panGestureEvent->GetVelocity().GetVelocityX()));
196         obj->SetProperty<double>(
197             "velocityY", PipelineBase::Px2VpWithCurrentDensity(panGestureEvent->GetVelocity().GetVelocityY()));
198         obj->SetProperty<double>("velocity",
199             PipelineBase::Px2VpWithCurrentDensity(panGestureEvent->GetVelocity().GetVelocityValue()));
200     }
201 }
202 
SetUniqueAttributes(JSRef<JSObject> & obj,GestureTypeName typeName,const std::shared_ptr<BaseGestureEvent> & info)203 void JsGestureJudgeFunction::SetUniqueAttributes(
204     JSRef<JSObject>& obj, GestureTypeName typeName, const std::shared_ptr<BaseGestureEvent>& info)
205 {
206     switch (typeName) {
207         case OHOS::Ace::GestureTypeName::LONG_PRESS_GESTURE: {
208             auto longPressGestureEvent = TypeInfoHelper::DynamicCast<LongPressGestureEvent>(info.get());
209             if (longPressGestureEvent) {
210                 obj->SetProperty<bool>("repeat", longPressGestureEvent->GetRepeat());
211             }
212             break;
213         }
214         case OHOS::Ace::GestureTypeName::PAN_GESTURE: {
215             ParsePanGestureEvent(obj, info);
216             break;
217         }
218         case OHOS::Ace::GestureTypeName::PINCH_GESTURE: {
219             auto pinchGestureEvent = TypeInfoHelper::DynamicCast<PinchGestureEvent>(info.get());
220             if (pinchGestureEvent) {
221                 obj->SetProperty<double>("scale", pinchGestureEvent->GetScale());
222                 obj->SetProperty<double>(
223                     "pinchCenterX", PipelineBase::Px2VpWithCurrentDensity(pinchGestureEvent->GetPinchCenter().GetX()));
224                 obj->SetProperty<double>(
225                     "pinchCenterY", PipelineBase::Px2VpWithCurrentDensity(pinchGestureEvent->GetPinchCenter().GetY()));
226             }
227             break;
228         }
229         case OHOS::Ace::GestureTypeName::ROTATION_GESTURE: {
230             auto rotationGestureEvent = TypeInfoHelper::DynamicCast<RotationGestureEvent>(info.get());
231             if (rotationGestureEvent) {
232                 obj->SetProperty<double>("angle", rotationGestureEvent->GetAngle());
233             }
234             break;
235         }
236         case OHOS::Ace::GestureTypeName::SWIPE_GESTURE: {
237             auto swipeGestureEvent = TypeInfoHelper::DynamicCast<SwipeGestureEvent>(info.get());
238             if (swipeGestureEvent) {
239                 obj->SetProperty<double>("angle", swipeGestureEvent->GetAngle());
240                 obj->SetProperty<double>("speed", swipeGestureEvent->GetSpeed());
241             }
242             break;
243         }
244         case OHOS::Ace::GestureTypeName::TAP_GESTURE: {
245             auto tapGestureEvent = TypeInfoHelper::DynamicCast<TapGestureEvent>(info.get());
246             if (tapGestureEvent && !tapGestureEvent->GetFingerList().empty()) {
247                 obj->SetPropertyObject("tapLocation", GetTapLocation(tapGestureEvent->GetFingerList().back()));
248             }
249             break;
250         }
251         default:
252             break;
253     }
254 }
255 
CreateGestureEventObject(const std::shared_ptr<BaseGestureEvent> & info,GestureTypeName typeName)256 JSRef<JSObject> JsGestureJudgeFunction::CreateGestureEventObject(
257     const std::shared_ptr<BaseGestureEvent>& info, GestureTypeName typeName)
258 {
259     JSRef<JSObjTemplate> objTemp = JSRef<JSObjTemplate>::New();
260     objTemp->SetInternalFieldCount(1);
261     JSRef<JSObject> obj = objTemp->NewInstance();
262     SetUniqueAttributes(obj, typeName, info);
263     obj->SetProperty<double>("timestamp", info->GetTimeStamp().time_since_epoch().count());
264     obj->SetProperty<double>("source", static_cast<int32_t>(info->GetSourceDevice()));
265     obj->SetProperty<double>("pressure", info->GetForce());
266     obj->SetProperty<double>("tiltX", info->GetTiltX().value_or(0.0f));
267     obj->SetProperty<double>("tiltY", info->GetTiltY().value_or(0.0f));
268     obj->SetProperty<double>("rollAngle", info->GetRollAngle().value_or(0.0f));
269     obj->SetProperty<double>("sourceTool", static_cast<int32_t>(info->GetSourceTool()));
270     obj->SetProperty<double>("deviceId", static_cast<int32_t>(info->GetDeviceId()));
271     obj->SetProperty<int32_t>("targetDisplayId", info->GetTargetDisplayId());
272     obj->SetProperty<float>("axisVertical", info->GetVerticalAxis());
273     obj->SetProperty<float>("axisHorizontal", info->GetHorizontalAxis());
274     obj->SetPropertyObject(
275         "getModifierKeyState", JSRef<JSFunc>::New<FunctionCallback>(NG::ArkTSUtils::JsGetModifierKeyState));
276 
277     JSRef<JSArray> fingerArr = JSRef<JSArray>::New();
278     const std::list<FingerInfo>& fingerList = info->GetFingerList();
279     std::list<FingerInfo> notTouchFingerList;
280     int32_t maxFingerId = -1;
281     for (const FingerInfo& fingerInfo : fingerList) {
282         JSRef<JSObject> element = CreateFingerInfo(fingerInfo);
283         if (fingerInfo.sourceType_ == SourceType::TOUCH && fingerInfo.sourceTool_ == SourceTool::FINGER) {
284             fingerArr->SetValueAt(fingerInfo.fingerId_, element);
285             if (fingerInfo.fingerId_ > maxFingerId) {
286                 maxFingerId = fingerInfo.fingerId_;
287             }
288         } else {
289             notTouchFingerList.emplace_back(fingerInfo);
290         }
291     }
292     auto idx = maxFingerId + 1;
293     for (const FingerInfo& fingerInfo : notTouchFingerList) {
294         JSRef<JSObject> element = CreateFingerInfo(fingerInfo);
295         fingerArr->SetValueAt(idx++, element);
296     }
297     obj->SetPropertyObject("fingerList", fingerArr);
298     auto target = CreateEventTargetObject(info);
299     obj->SetPropertyObject("target", target);
300     CreateFingerInfosObject(info, obj);
301     obj->Wrap<BaseGestureEvent>(info.get());
302     return obj;
303 }
304 
CreateFingerInfosObject(const std::shared_ptr<BaseGestureEvent> & info,JSRef<JSObject> & obj)305 JSRef<JSObject> JsGestureJudgeFunction::CreateFingerInfosObject(
306     const std::shared_ptr<BaseGestureEvent>& info, JSRef<JSObject>& obj)
307 {
308     JSRef<JSArray> fingerArr = JSRef<JSArray>::New();
309     const std::list<FingerInfo>& fingerList = info->GetFingerList();
310     std::list<FingerInfo> notTouchFingerList;
311     std::vector<JSRef<JSObject>> validFingers;
312     for (const FingerInfo& fingerInfo : fingerList) {
313         JSRef<JSObject> element = CreateFingerInfo(fingerInfo);
314         if (fingerInfo.sourceType_ == SourceType::TOUCH && fingerInfo.sourceTool_ == SourceTool::FINGER) {
315             validFingers.emplace_back(element);
316         } else {
317             notTouchFingerList.emplace_back(fingerInfo);
318         }
319     }
320     for (size_t i = 0; i < validFingers.size(); ++i) {
321         fingerArr->SetValueAt(i, validFingers[i]);
322     }
323     auto idx = validFingers.size();
324     for (const FingerInfo& fingerInfo : notTouchFingerList) {
325         JSRef<JSObject> element = CreateFingerInfo(fingerInfo);
326         fingerArr->SetValueAt(idx++, element);
327     }
328     obj->SetPropertyObject("fingerInfos", fingerArr);
329     return obj;
330 }
331 } // namespace OHOS::Ace::Framework
332