1 /*
2 * Copyright (c) 2021-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/jsview/js_gesture.h"
17
18 #include "base/log/log_wrapper.h"
19 #include "bridge/common/utils/engine_helper.h"
20 #include "bridge/declarative_frontend/jsview/models/gesture_model_impl.h"
21 #include "core/components_ng/base/view_stack_model.h"
22 #include "core/components_ng/pattern/gesture/gesture_model_ng.h"
23 #include "frameworks/base/log/ace_scoring_log.h"
24 #include "frameworks/bridge/declarative_frontend/engine/functions/js_gesture_function.h"
25 #include "frameworks/core/gestures/timeout_gesture.h"
26
27 namespace OHOS::Ace {
28 std::unique_ptr<GestureModel> GestureModel::instance_ = nullptr;
29 std::mutex GestureModel::mutex_;
GetInstance()30 GestureModel* GestureModel::GetInstance()
31 {
32 if (!instance_) {
33 std::lock_guard<std::mutex> lock(mutex_);
34 if (!instance_) {
35 #ifdef NG_BUILD
36 instance_.reset(new NG::GestureModelNG());
37 #else
38 if (Container::IsCurrentUseNewPipeline()) {
39 instance_.reset(new NG::GestureModelNG());
40 } else {
41 instance_.reset(new Framework::GestureModelImpl());
42 }
43 #endif
44 }
45 }
46 return instance_.get();
47 }
48
49 std::unique_ptr<TapGestureModel> TapGestureModel::instance_ = nullptr;
50 std::mutex TapGestureModel::mutex_;
GetInstance()51 TapGestureModel* TapGestureModel::GetInstance()
52 {
53 if (!instance_) {
54 std::lock_guard<std::mutex> lock(mutex_);
55 if (!instance_) {
56 #ifdef NG_BUILD
57 instance_.reset(new NG::TapGestureModelNG());
58 #else
59 if (Container::IsCurrentUseNewPipeline()) {
60 instance_.reset(new NG::TapGestureModelNG());
61 } else {
62 instance_.reset(new Framework::TapGestureModelImpl());
63 }
64 #endif
65 }
66 }
67 return instance_.get();
68 }
69
70 std::unique_ptr<LongPressGestureModel> LongPressGestureModel::instance_ = nullptr;
71 std::mutex LongPressGestureModel::mutex_;
GetInstance()72 LongPressGestureModel* LongPressGestureModel::GetInstance()
73 {
74 if (!instance_) {
75 std::lock_guard<std::mutex> lock(mutex_);
76 if (!instance_) {
77 #ifdef NG_BUILD
78 instance_.reset(new NG::LongPressGestureModelNG());
79 #else
80 if (Container::IsCurrentUseNewPipeline()) {
81 instance_.reset(new NG::LongPressGestureModelNG());
82 } else {
83 instance_.reset(new Framework::LongPressGestureModelImpl());
84 }
85 #endif
86 }
87 }
88 return instance_.get();
89 }
90
91 std::unique_ptr<PanGestureModel> PanGestureModel::instance_ = nullptr;
92 std::mutex PanGestureModel::mutex_;
GetInstance()93 PanGestureModel* PanGestureModel::GetInstance()
94 {
95 if (!instance_) {
96 std::lock_guard<std::mutex> lock(mutex_);
97 if (!instance_) {
98 #ifdef NG_BUILD
99 instance_.reset(new NG::PanGestureModelNG());
100 #else
101 if (Container::IsCurrentUseNewPipeline()) {
102 instance_.reset(new NG::PanGestureModelNG());
103 } else {
104 instance_.reset(new Framework::PanGestureModelImpl());
105 }
106 #endif
107 }
108 }
109 return instance_.get();
110 }
111
112 std::unique_ptr<SwipeGestureModel> SwipeGestureModel::instance_ = nullptr;
113 std::mutex SwipeGestureModel::mutex_;
GetInstance()114 SwipeGestureModel* SwipeGestureModel::GetInstance()
115 {
116 if (!instance_) {
117 std::lock_guard<std::mutex> lock(mutex_);
118 if (!instance_) {
119 #ifdef NG_BUILD
120 instance_.reset(new NG::SwipeGestureModelNG());
121 #else
122 if (Container::IsCurrentUseNewPipeline()) {
123 instance_.reset(new NG::SwipeGestureModelNG());
124 } else {
125 instance_.reset(new Framework::SwipeGestureModelImpl());
126 }
127 #endif
128 }
129 }
130 return instance_.get();
131 }
132
133 std::unique_ptr<PinchGestureModel> PinchGestureModel::instance_ = nullptr;
134 std::mutex PinchGestureModel::mutex_;
GetInstance()135 PinchGestureModel* PinchGestureModel::GetInstance()
136 {
137 if (!instance_) {
138 std::lock_guard<std::mutex> lock(mutex_);
139 if (!instance_) {
140 #ifdef NG_BUILD
141 instance_.reset(new NG::PinchGestureModelNG());
142 #else
143 if (Container::IsCurrentUseNewPipeline()) {
144 instance_.reset(new NG::PinchGestureModelNG());
145 } else {
146 instance_.reset(new Framework::PinchGestureModelImpl());
147 }
148 #endif
149 }
150 }
151 return instance_.get();
152 }
153
154 std::unique_ptr<RotationGestureModel> RotationGestureModel::instance_ = nullptr;
155 std::mutex RotationGestureModel::mutex_;
GetInstance()156 RotationGestureModel* RotationGestureModel::GetInstance()
157 {
158 if (!instance_) {
159 std::lock_guard<std::mutex> lock(mutex_);
160 if (!instance_) {
161 #ifdef NG_BUILD
162 instance_.reset(new NG::RotationGestureModelNG());
163 #else
164 if (Container::IsCurrentUseNewPipeline()) {
165 instance_.reset(new NG::RotationGestureModelNG());
166 } else {
167 instance_.reset(new Framework::RotationGestureModelImpl());
168 }
169 #endif
170 }
171 }
172 return instance_.get();
173 }
174
175 std::unique_ptr<GestureGroupModel> GestureGroupModel::instance_ = nullptr;
176 std::mutex GestureGroupModel::mutex_;
GetInstance()177 GestureGroupModel* GestureGroupModel::GetInstance()
178 {
179 if (!instance_) {
180 std::lock_guard<std::mutex> lock(mutex_);
181 if (!instance_) {
182 #ifdef NG_BUILD
183 instance_.reset(new NG::GestureGroupModelNG());
184 #else
185 if (Container::IsCurrentUseNewPipeline()) {
186 instance_.reset(new NG::GestureGroupModelNG());
187 } else {
188 instance_.reset(new Framework::GestureGroupModelImpl());
189 }
190 #endif
191 }
192 }
193 return instance_.get();
194 }
195
196 std::unique_ptr<TimeoutGestureModel> TimeoutGestureModel::instance_ = nullptr;
197 std::mutex TimeoutGestureModel::mutex_;
GetInstance()198 TimeoutGestureModel* TimeoutGestureModel::GetInstance()
199 {
200 if (!instance_) {
201 std::lock_guard<std::mutex> lock(mutex_);
202 if (!instance_) {
203 #ifdef NG_BUILD
204 instance_.reset(new NG::TimeoutGestureModelNG());
205 #else
206 if (Container::IsCurrentUseNewPipeline()) {
207 instance_.reset(new NG::TimeoutGestureModelNG());
208 } else {
209 instance_.reset(new Framework::TimeoutGestureModelImpl());
210 }
211 #endif
212 }
213 }
214 return instance_.get();
215 }
216 } // namespace OHOS::Ace
217
218 namespace OHOS::Ace::Framework {
219 namespace {
220 constexpr int32_t DEFAULT_TAP_FINGER = 1;
221 constexpr int32_t DEFAULT_TAP_COUNT = 1;
222 constexpr double DEFAULT_TAP_DISTANCE = std::numeric_limits<double>::infinity();
223 constexpr int32_t DEFAULT_LONG_PRESS_FINGER = 1;
224 constexpr int32_t DEFAULT_LONG_PRESS_DURATION = 500;
225 constexpr int32_t DEFAULT_PINCH_FINGER = 2;
226 constexpr int32_t DEFAULT_MAX_PINCH_FINGER = 5;
227 constexpr double DEFAULT_PINCH_DISTANCE = 5.0;
228 constexpr int32_t DEFAULT_PAN_FINGER = 1;
229 constexpr int32_t DEFAULT_MAX_PAN_FINGERS = 10;
230 constexpr Dimension DEFAULT_PAN_DISTANCE = 5.0_vp;
231 constexpr int32_t DEFAULT_SLIDE_FINGER = DEFAULT_PAN_FINGER;
232 constexpr double DEFAULT_SLIDE_SPEED = 100.0;
233 constexpr int32_t DEFAULT_ROTATION_FINGER = 2;
234 constexpr double DEFAULT_ROTATION_ANGLE = 1.0;
235
236 constexpr char GESTURE_FINGERS[] = "fingers";
237 constexpr char GESTURE_DISTANCE[] = "distance";
238 constexpr char TAP_GESTURE_DISTANCE[] = "distanceThreshold";
239 constexpr char GESTURE_SPEED[] = "speed";
240 constexpr char TAP_COUNT[] = "count";
241 constexpr char LONG_PRESS_REPEAT[] = "repeat";
242 constexpr char LONG_PRESS_DURATION[] = "duration";
243 constexpr char PAN_DIRECTION[] = "direction";
244 constexpr char SWIPE_DIRECTION[] = "direction";
245 constexpr char ROTATION_ANGLE[] = "angle";
246 constexpr char LIMIT_FINGER_COUNT[] = "isFingerCountLimited";
247 constexpr char GESTURE_DISTANCE_MAP[] = "distanceMap";
248 } // namespace
249
Create(const JSCallbackInfo & info)250 void JSGesture::Create(const JSCallbackInfo& info)
251 {
252 int32_t priorityNum = 0;
253 if (info.Length() > 0) {
254 auto jsPriorityNum = info[0];
255 if (jsPriorityNum->IsNumber()) {
256 priorityNum = jsPriorityNum->ToNumber<int32_t>();
257 }
258 }
259
260 int32_t gestureMaskNum = 0;
261 if (info.Length() > 1) {
262 auto jsGestureMaskNum = info[1];
263 if (jsGestureMaskNum->IsNumber()) {
264 gestureMaskNum = jsGestureMaskNum->ToNumber<int32_t>();
265 }
266 }
267
268 GestureModel::GetInstance()->Create(priorityNum, gestureMaskNum);
269 }
270
Finish()271 void JSGesture::Finish()
272 {
273 if (ViewStackModel::GetInstance()->IsPrebuilding()) {
274 return ViewStackModel::GetInstance()->PushPrebuildCompCmd("[JSGesture][pop]", &JSGesture::Finish);
275 }
276 GestureModel::GetInstance()->Finish();
277 }
278
Pop()279 void JSGesture::Pop()
280 {
281 if (ViewStackModel::GetInstance()->IsPrebuilding()) {
282 return ViewStackModel::GetInstance()->PushPrebuildCompCmd("[JSGesture][pop]", &JSGesture::Pop);
283 }
284 GestureModel::GetInstance()->Pop();
285 }
286
Create(const JSCallbackInfo & args)287 void JSTapGesture::Create(const JSCallbackInfo& args)
288 {
289 int32_t countNum = DEFAULT_TAP_COUNT;
290 int32_t fingersNum = DEFAULT_TAP_FINGER;
291 double distanceThresholdNum = DEFAULT_TAP_DISTANCE;
292 bool isLimitFingerCount = false;
293 if (args.Length() > 0 && args[0]->IsObject()) {
294 JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
295 JSRef<JSVal> count = obj->GetProperty(TAP_COUNT);
296 JSRef<JSVal> fingers = obj->GetProperty(GESTURE_FINGERS);
297 JSRef<JSVal> distanceThreshold = obj->GetProperty(TAP_GESTURE_DISTANCE);
298 JSRef<JSVal> limitFingerCount = obj->GetProperty(LIMIT_FINGER_COUNT);
299
300 if (count->IsNumber()) {
301 int32_t countNumber = count->ToNumber<int32_t>();
302 countNum = countNumber <= DEFAULT_TAP_COUNT ? DEFAULT_TAP_COUNT : countNumber;
303 }
304 if (fingers->IsNumber()) {
305 int32_t fingersNumber = fingers->ToNumber<int32_t>();
306 fingersNum = fingersNumber <= DEFAULT_TAP_FINGER ? DEFAULT_TAP_FINGER : fingersNumber;
307 }
308 if (distanceThreshold->IsNumber()) {
309 double distanceThresholdNumber = distanceThreshold->ToNumber<double>();
310 distanceThresholdNum = distanceThresholdNumber < 0? DEFAULT_TAP_DISTANCE : distanceThresholdNumber;
311 distanceThresholdNum = Dimension(distanceThresholdNum, DimensionUnit::VP).ConvertToPx();
312 }
313 if (limitFingerCount->IsBoolean()) {
314 isLimitFingerCount = limitFingerCount->ToBoolean();
315 }
316 }
317
318 TapGestureModel::GetInstance()->Create(countNum, fingersNum, distanceThresholdNum, isLimitFingerCount);
319 }
320
Create(const JSCallbackInfo & args)321 void JSLongPressGesture::Create(const JSCallbackInfo& args)
322 {
323 int32_t fingersNum = DEFAULT_LONG_PRESS_FINGER;
324 bool repeatResult = false;
325 int32_t durationNum = DEFAULT_LONG_PRESS_DURATION;
326 bool isLimitFingerCount = false;
327 if (args.Length() > 0 && args[0]->IsObject()) {
328 JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
329 JSRef<JSVal> fingers = obj->GetProperty(GESTURE_FINGERS);
330 JSRef<JSVal> repeat = obj->GetProperty(LONG_PRESS_REPEAT);
331 JSRef<JSVal> duration = obj->GetProperty(LONG_PRESS_DURATION);
332 JSRef<JSVal> limitFingerCount = obj->GetProperty(LIMIT_FINGER_COUNT);
333
334 if (fingers->IsNumber()) {
335 int32_t fingersNumber = fingers->ToNumber<int32_t>();
336 fingersNum = fingersNumber <= DEFAULT_LONG_PRESS_FINGER ? DEFAULT_LONG_PRESS_FINGER : fingersNumber;
337 }
338 if (repeat->IsBoolean()) {
339 repeatResult = repeat->ToBoolean();
340 }
341 if (duration->IsNumber()) {
342 int32_t durationNumber = duration->ToNumber<int32_t>();
343 durationNum = durationNumber <= 0 ? DEFAULT_LONG_PRESS_DURATION : durationNumber;
344 }
345 if (limitFingerCount->IsBoolean()) {
346 isLimitFingerCount = limitFingerCount->ToBoolean();
347 }
348 }
349 LongPressGestureModel::GetInstance()->Create(fingersNum, repeatResult, durationNum, isLimitFingerCount);
350 }
351
GetIteratorNext(const napi_env env,napi_value iterator,napi_value func,bool * done)352 napi_value GetIteratorNext(const napi_env env, napi_value iterator, napi_value func, bool *done)
353 {
354 napi_value next = nullptr;
355 NAPI_CALL(env, napi_call_function(env, iterator, func, 0, nullptr, &next));
356 napi_value doneValue = nullptr;
357 NAPI_CALL(env, napi_get_named_property(env, next, "done", &doneValue));
358 NAPI_CALL(env, napi_get_value_bool(env, doneValue, done));
359 return next;
360 }
361
ParsePanDistanceMap(JSRef<JSVal> jsDistanceMap,PanDistanceMapDimension & distanceMap)362 napi_value JSPanGesture::ParsePanDistanceMap(JSRef<JSVal> jsDistanceMap, PanDistanceMapDimension& distanceMap)
363 {
364 napi_value emptyValue = nullptr;
365 auto engine = EngineHelper::GetCurrentEngine();
366 CHECK_NULL_RETURN(engine, emptyValue);
367 NativeEngine* nativeEngine = engine->GetNativeEngine();
368 CHECK_NULL_RETURN(nativeEngine, emptyValue);
369 auto env = reinterpret_cast<napi_env>(nativeEngine);
370
371 auto jsVal = JSRef<JSVal>::Cast(jsDistanceMap);
372 panda::Local<JsiValue> value = jsVal.Get().GetLocalHandle();
373 JSValueWrapper valueWrapper = value;
374 napi_value nativeValue = nativeEngine->ValueToNapiValue(valueWrapper);
375
376 // parse map object
377 napi_value entriesFunc = nullptr;
378 napi_value iterator = nullptr;
379 napi_value nextFunc = nullptr;
380 NAPI_CALL(env, napi_get_named_property(env, nativeValue, "entries", &entriesFunc));
381 NAPI_CALL(env, napi_call_function(env, nativeValue, entriesFunc, 0, nullptr, &iterator));
382 NAPI_CALL(env, napi_get_named_property(env, iterator, "next", &nextFunc));
383
384 bool done = false;
385 napi_value next = nullptr;
386 while ((next = GetIteratorNext(env, iterator, nextFunc, &done)) != nullptr && !done) {
387 napi_value entry = nullptr;
388 napi_value key = nullptr;
389 napi_value value = nullptr;
390 NAPI_CALL(env, napi_get_named_property(env, next, "value", &entry));
391 NAPI_CALL(env, napi_get_element(env, entry, 0, &key));
392 NAPI_CALL(env, napi_get_element(env, entry, 1, &value));
393 napi_valuetype kType = napi_undefined;
394 NAPI_CALL(env, napi_typeof(env, key, &kType));
395 napi_valuetype vType = napi_undefined;
396 NAPI_CALL(env, napi_typeof(env, value, &vType));
397 if (kType != napi_number || vType != napi_number) {
398 continue;
399 }
400 int32_t sourceTool = 0;
401 NAPI_CALL(env, napi_get_value_int32(env, key, &sourceTool));
402 double distance = 0.0;
403 NAPI_CALL(env, napi_get_value_double(env, value, &distance));
404 SourceTool st = static_cast<SourceTool>(sourceTool);
405 if (st >= SourceTool::UNKNOWN && st <= SourceTool::JOYSTICK && GreatOrEqual(distance, 0.0)) {
406 Dimension dimension = Dimension(distance, DimensionUnit::VP);
407 distanceMap[st] = dimension;
408 }
409 }
410 return next;
411 }
412
ParsePanDistance(const JSRef<JSObject> & obj,PanDistanceMapDimension & distanceMap)413 void JSPanGesture::ParsePanDistance(const JSRef<JSObject>& obj, PanDistanceMapDimension& distanceMap)
414 {
415 JSRef<JSVal> distance = obj->GetProperty(GESTURE_DISTANCE);
416 JSRef<JSVal> jsDistanceMap = obj->GetProperty(GESTURE_DISTANCE_MAP);
417 if (jsDistanceMap->IsObject()) {
418 distanceMap = { { SourceTool::UNKNOWN, DEFAULT_PAN_DISTANCE }, {
419 SourceTool::PEN, DEFAULT_PEN_PAN_DISTANCE } };
420 ParsePanDistanceMap(jsDistanceMap, distanceMap);
421 return;
422 }
423 if (distance->IsNumber()) {
424 double distanceNumber = distance->ToNumber<double>();
425 if (!LessNotEqual(distanceNumber, 0.0)) {
426 Dimension dimension = Dimension(distanceNumber, DimensionUnit::VP);
427 distanceMap[SourceTool::UNKNOWN] = dimension;
428 } else {
429 distanceMap[SourceTool::PEN] = DEFAULT_PEN_PAN_DISTANCE;
430 }
431 } else {
432 distanceMap[SourceTool::PEN] = DEFAULT_PEN_PAN_DISTANCE;
433 }
434 }
435
Create(const JSCallbackInfo & args)436 void JSPanGesture::Create(const JSCallbackInfo& args)
437 {
438 int32_t fingersNum = DEFAULT_PAN_FINGER;
439 bool isLimitFingerCount = false;
440 PanDirection panDirection;
441 PanDistanceMapDimension distanceMap = { { SourceTool::UNKNOWN, DEFAULT_PAN_DISTANCE } };
442 if (args.Length() <= 0 || !args[0]->IsObject()) {
443 distanceMap[SourceTool::PEN] = DEFAULT_PEN_PAN_DISTANCE;
444 PanGestureModel::GetInstance()->Create(fingersNum, panDirection, distanceMap, isLimitFingerCount);
445 return;
446 }
447
448 JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
449 JSPanGestureOption* panGestureOption = obj->Unwrap<JSPanGestureOption>();
450
451 if (panGestureOption != nullptr) {
452 RefPtr<PanGestureOption> refPanGestureOption = panGestureOption->GetPanGestureOption();
453 PanGestureModel::GetInstance()->SetPanGestureOption(refPanGestureOption);
454 return;
455 }
456
457 JSRef<JSVal> fingers = obj->GetProperty(GESTURE_FINGERS);
458 JSRef<JSVal> directionNum = obj->GetProperty(PAN_DIRECTION);
459 JSRef<JSVal> limitFingerCount = obj->GetProperty(LIMIT_FINGER_COUNT);
460
461 if (fingers->IsNumber()) {
462 int32_t fingersNumber = fingers->ToNumber<int32_t>();
463 fingersNum = fingersNumber <= DEFAULT_PAN_FINGER ? DEFAULT_PAN_FINGER : fingersNumber;
464 }
465 if (directionNum->IsNumber()) {
466 uint32_t directNum = directionNum->ToNumber<uint32_t>();
467 if (directNum >= static_cast<uint32_t>(PanDirection::NONE) &&
468 directNum <= static_cast<uint32_t>(PanDirection::ALL)) {
469 panDirection.type = directNum;
470 }
471 }
472 if (limitFingerCount->IsBoolean()) {
473 isLimitFingerCount = limitFingerCount->ToBoolean();
474 }
475 ParsePanDistance(obj, distanceMap);
476 PanGestureModel::GetInstance()->Create(fingersNum, panDirection, distanceMap, isLimitFingerCount);
477 }
478
Create(const JSCallbackInfo & args)479 void JSSwipeGesture::Create(const JSCallbackInfo& args)
480 {
481 int32_t fingersNum = DEFAULT_SLIDE_FINGER;
482 double speedNum = DEFAULT_SLIDE_SPEED;
483 SwipeDirection slideDirection;
484 bool isLimitFingerCount = false;
485
486 if (args.Length() <= 0 || !args[0]->IsObject()) {
487 SwipeGestureModel::GetInstance()->Create(fingersNum, slideDirection, speedNum, isLimitFingerCount);
488 return;
489 }
490
491 JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
492 JSRef<JSVal> fingers = obj->GetProperty(GESTURE_FINGERS);
493 JSRef<JSVal> speed = obj->GetProperty(GESTURE_SPEED);
494 JSRef<JSVal> directionNum = obj->GetProperty(SWIPE_DIRECTION);
495 JSRef<JSVal> limitFingerCount = obj->GetProperty(LIMIT_FINGER_COUNT);
496
497 if (fingers->IsNumber()) {
498 int32_t fingersNumber = fingers->ToNumber<int32_t>();
499 fingersNum = fingersNumber <= DEFAULT_PAN_FINGER ? DEFAULT_PAN_FINGER : fingersNumber;
500 }
501 if (speed->IsNumber()) {
502 double speedNumber = speed->ToNumber<double>();
503 speedNum = LessOrEqual(speedNumber, 0.0) ? DEFAULT_SLIDE_SPEED : speedNumber;
504 }
505 if (directionNum->IsNumber()) {
506 uint32_t directNum = directionNum->ToNumber<uint32_t>();
507 if (directNum >= static_cast<uint32_t>(SwipeDirection::NONE) &&
508 directNum <= static_cast<uint32_t>(SwipeDirection::ALL)) {
509 slideDirection.type = directNum;
510 }
511 }
512 if (limitFingerCount->IsBoolean()) {
513 isLimitFingerCount = limitFingerCount->ToBoolean();
514 }
515
516 SwipeGestureModel::GetInstance()->Create(fingersNum, slideDirection, speedNum, isLimitFingerCount);
517 }
518
Create(const JSCallbackInfo & args)519 void JSPinchGesture::Create(const JSCallbackInfo& args)
520 {
521 int32_t fingersNum = DEFAULT_PINCH_FINGER;
522 double distanceNum = DEFAULT_PINCH_DISTANCE;
523 bool isLimitFingerCount = false;
524 if (args.Length() > 0 && args[0]->IsObject()) {
525 JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
526 JSRef<JSVal> fingers = obj->GetProperty(GESTURE_FINGERS);
527 JSRef<JSVal> distance = obj->GetProperty(GESTURE_DISTANCE);
528 JSRef<JSVal> limitFingerCount = obj->GetProperty(LIMIT_FINGER_COUNT);
529
530 if (fingers->IsNumber()) {
531 int32_t fingersNumber = fingers->ToNumber<int32_t>();
532 fingersNum = fingersNumber <= DEFAULT_PINCH_FINGER ? DEFAULT_PINCH_FINGER : fingersNumber;
533 fingersNum = fingersNum > DEFAULT_MAX_PINCH_FINGER ? DEFAULT_PINCH_FINGER : fingersNum;
534 }
535 if (distance->IsNumber()) {
536 double distanceNumber = distance->ToNumber<double>();
537 distanceNum = LessNotEqual(distanceNumber, 0.0) ? DEFAULT_PINCH_DISTANCE : distanceNumber;
538 }
539 if (limitFingerCount->IsBoolean()) {
540 isLimitFingerCount = limitFingerCount->ToBoolean();
541 }
542 }
543
544 PinchGestureModel::GetInstance()->Create(fingersNum, distanceNum, isLimitFingerCount);
545 }
546
Create(const JSCallbackInfo & args)547 void JSRotationGesture::Create(const JSCallbackInfo& args)
548 {
549 double angleNum = DEFAULT_ROTATION_ANGLE;
550 int32_t fingersNum = DEFAULT_ROTATION_FINGER;
551 bool isLimitFingerCount = false;
552 if (args.Length() > 0 && args[0]->IsObject()) {
553 JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
554 JSRef<JSVal> fingers = obj->GetProperty(GESTURE_FINGERS);
555 JSRef<JSVal> angle = obj->GetProperty(ROTATION_ANGLE);
556 JSRef<JSVal> limitFingerCount = obj->GetProperty(LIMIT_FINGER_COUNT);
557
558 if (fingers->IsNumber()) {
559 int32_t fingersNumber = fingers->ToNumber<int32_t>();
560 fingersNum = fingersNumber <= DEFAULT_ROTATION_FINGER ? DEFAULT_ROTATION_FINGER : fingersNumber;
561 }
562 if (angle->IsNumber()) {
563 double angleNumber = angle->ToNumber<double>();
564 angleNum = LessNotEqual(angleNumber, 0.0) ? DEFAULT_ROTATION_ANGLE : angleNumber;
565 }
566 if (limitFingerCount->IsBoolean()) {
567 isLimitFingerCount = limitFingerCount->ToBoolean();
568 }
569 }
570
571 RotationGestureModel::GetInstance()->Create(fingersNum, angleNum, isLimitFingerCount);
572 }
573
Create(const JSCallbackInfo & args)574 void JSGestureGroup::Create(const JSCallbackInfo& args)
575 {
576 int32_t gestureMode = 0;
577 if (args.Length() > 0) {
578 auto jsGestureMode = args[0];
579 if (jsGestureMode->IsNumber()) {
580 gestureMode = jsGestureMode->ToNumber<int32_t>();
581 }
582 }
583
584 GestureGroupModel::GetInstance()->Create(gestureMode);
585 }
586
JsHandlerOnGestureEvent(Ace::GestureEventAction action,const JSCallbackInfo & args)587 void JSGesture::JsHandlerOnGestureEvent(Ace::GestureEventAction action, const JSCallbackInfo& args)
588 {
589 if (args.Length() < 1 || !args[0]->IsFunction()) {
590 return;
591 }
592
593 RefPtr<JsGestureFunction> handlerFunc = AceType::MakeRefPtr<JsGestureFunction>(JSRef<JSFunc>::Cast(args[0]));
594
595 if (action == Ace::GestureEventAction::CANCEL) {
596 auto onActionCancelFunc = [execCtx = args.GetExecutionContext(), func = std::move(handlerFunc)](
597 GestureEvent& info) {
598 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
599 ACE_SCORING_EVENT("Gesture.onCancel");
600 func->Execute(info);
601 };
602 GestureModel::GetInstance()->SetOnGestureEvent(onActionCancelFunc);
603 return;
604 }
605
606 auto onActionFunc = [execCtx = args.GetExecutionContext(), func = std::move(handlerFunc)](GestureEvent& info) {
607 JAVASCRIPT_EXECUTION_SCOPE_WITH_CHECK(execCtx);
608 ACE_SCORING_EVENT("Gesture.onActionCancel");
609 func->Execute(info);
610 };
611
612 GestureModel::GetInstance()->SetOnActionFunc(onActionFunc, action);
613 }
614
SetTag(const JSCallbackInfo & args)615 void JSGesture::SetTag(const JSCallbackInfo& args)
616 {
617 std::string tag;
618 if (args.Length() > 0) {
619 auto jsTag = args[0];
620 if (jsTag->IsString()) {
621 tag = jsTag->ToString();
622 }
623 }
624 GestureModel::GetInstance()->SetTag(tag);
625 }
626
SetAllowedTypes(const JSCallbackInfo & args)627 void JSGesture::SetAllowedTypes(const JSCallbackInfo& args)
628 {
629 if (args.Length() < 1) {
630 return;
631 }
632
633 JSRef<JSVal> jsTypes = args[0];
634 if (!jsTypes->IsArray()) {
635 return;
636 }
637 JSRef<JSArray> jsTypesArr = JSRef<JSArray>::Cast(jsTypes);
638 std::set<SourceTool> allowedTypes{};
639 auto typesArrLength = jsTypesArr->Length();
640 for (size_t i = 0; i < typesArrLength; ++i) {
641 auto type = jsTypesArr->GetValueAt(i);
642 if (type->IsNumber()) {
643 allowedTypes.insert(static_cast<SourceTool>(type->ToNumber<int32_t>()));
644 }
645 }
646 if (allowedTypes.empty()) {
647 return;
648 }
649 GestureModel::GetInstance()->SetAllowedTypes(allowedTypes);
650 }
651
JsHandlerOnAction(const JSCallbackInfo & args)652 void JSGesture::JsHandlerOnAction(const JSCallbackInfo& args)
653 {
654 JSGesture::JsHandlerOnGestureEvent(Ace::GestureEventAction::ACTION, args);
655 }
JsHandlerOnActionStart(const JSCallbackInfo & args)656 void JSGesture::JsHandlerOnActionStart(const JSCallbackInfo& args)
657 {
658 JSGesture::JsHandlerOnGestureEvent(Ace::GestureEventAction::START, args);
659 }
JsHandlerOnActionUpdate(const JSCallbackInfo & args)660 void JSGesture::JsHandlerOnActionUpdate(const JSCallbackInfo& args)
661 {
662 JSGesture::JsHandlerOnGestureEvent(Ace::GestureEventAction::UPDATE, args);
663 }
664
JsHandlerOnActionEnd(const JSCallbackInfo & args)665 void JSGesture::JsHandlerOnActionEnd(const JSCallbackInfo& args)
666 {
667 JSGesture::JsHandlerOnGestureEvent(Ace::GestureEventAction::END, args);
668 }
JsHandlerOnActionCancel(const JSCallbackInfo & args)669 void JSGesture::JsHandlerOnActionCancel(const JSCallbackInfo& args)
670 {
671 JSGesture::JsHandlerOnGestureEvent(Ace::GestureEventAction::CANCEL, args);
672 }
673
JSBind(BindingTarget globalObj)674 void JSPanGestureOption::JSBind(BindingTarget globalObj)
675 {
676 JSClass<JSPanGestureOption>::Declare("PanGestureOption");
677 JSClass<JSPanGestureOption>::CustomMethod("setDirection", &JSPanGestureOption::SetDirection);
678 JSClass<JSPanGestureOption>::CustomMethod("setDistance", &JSPanGestureOption::SetDistance);
679 JSClass<JSPanGestureOption>::CustomMethod("setFingers", &JSPanGestureOption::SetFingers);
680 JSClass<JSPanGestureOption>::Bind(globalObj, &JSPanGestureOption::Constructor, &JSPanGestureOption::Destructor);
681
682 JSClass<JSPanGestureOption>::Declare("PanGestureOptions");
683 JSClass<JSPanGestureOption>::CustomMethod("setDirection", &JSPanGestureOption::SetDirection);
684 JSClass<JSPanGestureOption>::CustomMethod("setDistance", &JSPanGestureOption::SetDistance);
685 JSClass<JSPanGestureOption>::CustomMethod("setFingers", &JSPanGestureOption::SetFingers);
686 JSClass<JSPanGestureOption>::CustomMethod("getDirection", &JSPanGestureOption::GetDirection);
687 JSClass<JSPanGestureOption>::CustomMethod("getDistance", &JSPanGestureOption::GetDistance);
688 JSClass<JSPanGestureOption>::Bind(globalObj, &JSPanGestureOption::Constructor, &JSPanGestureOption::Destructor);
689 }
690
SetDirection(const JSCallbackInfo & args)691 void JSPanGestureOption::SetDirection(const JSCallbackInfo& args)
692 {
693 if (args.Length() > 0 && args[0]->IsNumber()) {
694 PanDirection direction = { args[0]->ToNumber<int32_t>() };
695 panGestureOption_->SetDirection(direction);
696 } else {
697 PanDirection directionAll = { PanDirection::ALL };
698 panGestureOption_->SetDirection(directionAll);
699 }
700 }
701
SetDistance(const JSCallbackInfo & args)702 void JSPanGestureOption::SetDistance(const JSCallbackInfo& args)
703 {
704 if (args.Length() > 0 && args[0]->IsNumber()) {
705 auto distance = args[0]->ToNumber<double>();
706 Dimension dimension =
707 LessNotEqual(distance, 0.0) ? DEFAULT_PAN_DISTANCE : Dimension(distance, DimensionUnit::VP);
708 panGestureOption_->SetDistance(dimension.ConvertToPx());
709 } else {
710 panGestureOption_->SetDistance(DEFAULT_PAN_DISTANCE.ConvertToPx());
711 }
712 }
713
SetFingers(const JSCallbackInfo & args)714 void JSPanGestureOption::SetFingers(const JSCallbackInfo& args)
715 {
716 if (args.Length() > 0 && args[0]->IsNumber()) {
717 auto fingers = args[0]->ToNumber<int32_t>();
718 fingers = fingers <= DEFAULT_PAN_FINGER ? DEFAULT_PAN_FINGER : fingers;
719 fingers = fingers > DEFAULT_MAX_PAN_FINGERS ? DEFAULT_PAN_FINGER : fingers;
720 panGestureOption_->SetFingers(fingers);
721 } else {
722 panGestureOption_->SetFingers(DEFAULT_PAN_FINGER);
723 }
724 }
725
GetDirection(const JSCallbackInfo & args)726 void JSPanGestureOption::GetDirection(const JSCallbackInfo& args)
727 {
728 PanDirection direction = { PanDirection::NONE };
729 if (panGestureOption_) {
730 direction = panGestureOption_->GetDirection();
731 }
732 args.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(static_cast<int32_t>(direction.type))));
733 }
734
GetDistance(const JSCallbackInfo & args)735 void JSPanGestureOption::GetDistance(const JSCallbackInfo& args)
736 {
737 double distance = 5;
738 double distance_new = distance;
739 if (panGestureOption_) {
740 distance = panGestureOption_->GetDistance();
741 auto context = PipelineContext::GetCurrentContextSafely();
742 CHECK_NULL_VOID(context);
743 distance_new = context->ConvertPxToVp(Dimension(distance, DimensionUnit::PX));
744 }
745 args.SetReturnValue(JSRef<JSVal>::Make(ToJSValue(RoundToMaxPrecision(distance_new))));
746 }
747
Constructor(const JSCallbackInfo & args)748 void JSPanGestureOption::Constructor(const JSCallbackInfo& args)
749 {
750 auto panGestureOption = Referenced::MakeRefPtr<JSPanGestureOption>();
751 panGestureOption->IncRefCount();
752 RefPtr<PanGestureOption> option = AceType::MakeRefPtr<PanGestureOption>();
753
754 int32_t fingersNum = DEFAULT_PAN_FINGER;
755 bool isLimitFingerCount = false;
756 PanDirection panDirection;
757 PanDistanceMapDimension distanceMap;
758 distanceMap[SourceTool::UNKNOWN] = DEFAULT_PAN_DISTANCE;
759
760 if (args.Length() > 0 && args[0]->IsObject()) {
761 JSRef<JSObject> obj = JSRef<JSObject>::Cast(args[0]);
762 JSRef<JSVal> fingers = obj->GetProperty(GESTURE_FINGERS);
763 JSRef<JSVal> distance = obj->GetProperty(GESTURE_DISTANCE);
764 JSRef<JSVal> directionNum = obj->GetProperty(PAN_DIRECTION);
765 JSRef<JSVal> limitFingerCount = obj->GetProperty(LIMIT_FINGER_COUNT);
766
767 if (fingers->IsNumber()) {
768 int32_t fingersNumber = fingers->ToNumber<int32_t>();
769 fingersNum = fingersNumber <= DEFAULT_PAN_FINGER ? DEFAULT_PAN_FINGER : fingersNumber;
770 }
771 if (distance->IsNumber()) {
772 double distanceNumber = distance->ToNumber<double>();
773 if (!LessNotEqual(distanceNumber, 0.0)) {
774 distanceMap[SourceTool::UNKNOWN] = Dimension(distanceNumber, DimensionUnit::VP);
775 } else {
776 distanceMap[SourceTool::PEN] = DEFAULT_PEN_PAN_DISTANCE;
777 }
778 } else {
779 distanceMap[SourceTool::PEN] = DEFAULT_PEN_PAN_DISTANCE;
780 }
781 if (directionNum->IsNumber()) {
782 uint32_t directNum = directionNum->ToNumber<uint32_t>();
783 if (directNum >= static_cast<uint32_t>(PanDirection::NONE) &&
784 directNum <= static_cast<uint32_t>(PanDirection::ALL)) {
785 panDirection.type = directNum;
786 }
787 }
788 if (limitFingerCount->IsBoolean()) {
789 isLimitFingerCount = limitFingerCount->ToBoolean();
790 }
791 }
792 option->SetDirection(panDirection);
793 option->SetDistanceMap(distanceMap);
794 option->SetDistance(distanceMap[SourceTool::UNKNOWN].ConvertToPx());
795 option->SetFingers(fingersNum);
796 option->SetIsLimitFingerCount(isLimitFingerCount);
797
798 panGestureOption->SetPanGestureOption(option);
799 args.SetReturnValue(Referenced::RawPtr(panGestureOption));
800 }
801
Destructor(JSPanGestureOption * panGestureOption)802 void JSPanGestureOption::Destructor(JSPanGestureOption* panGestureOption)
803 {
804 if (panGestureOption != nullptr) {
805 panGestureOption->DecRefCount();
806 }
807 }
808
JSBind(BindingTarget globalObj)809 void JSGesture::JSBind(BindingTarget globalObj)
810 {
811 JSClass<JSGesture>::Declare("Gesture");
812 MethodOptions opt = MethodOptions::NONE;
813 JSClass<JSGesture>::StaticMethod("create", &JSGesture::Create, opt);
814 JSClass<JSGesture>::StaticMethod("pop", &JSGesture::Finish);
815 JSClass<JSGesture>::Bind<>(globalObj);
816
817 JSClass<JSTapGesture>::Declare("TapGesture");
818 JSClass<JSTapGesture>::StaticMethod("create", &JSTapGesture::Create, opt);
819 JSClass<JSTapGesture>::StaticMethod("tag", &JSGesture::SetTag, opt);
820 JSClass<JSTapGesture>::StaticMethod("allowedTypes", &JSGesture::SetAllowedTypes);
821 JSClass<JSTapGesture>::StaticMethod("pop", &JSGesture::Pop);
822 JSClass<JSTapGesture>::StaticMethod("onAction", &JSGesture::JsHandlerOnAction);
823 JSClass<JSTapGesture>::StaticMethod("onActionUpdate", &JSGesture::JsHandlerOnActionUpdate);
824 JSClass<JSTapGesture>::Bind<>(globalObj);
825
826 JSClass<JSLongPressGesture>::Declare("LongPressGesture");
827 JSClass<JSLongPressGesture>::StaticMethod("create", &JSLongPressGesture::Create, opt);
828 JSClass<JSLongPressGesture>::StaticMethod("tag", &JSGesture::SetTag, opt);
829 JSClass<JSLongPressGesture>::StaticMethod("allowedTypes", &JSGesture::SetAllowedTypes);
830 JSClass<JSLongPressGesture>::StaticMethod("pop", &JSGesture::Pop);
831 JSClass<JSLongPressGesture>::StaticMethod("onAction", &JSGesture::JsHandlerOnAction);
832 JSClass<JSLongPressGesture>::StaticMethod("onActionEnd", &JSGesture::JsHandlerOnActionEnd);
833 JSClass<JSLongPressGesture>::StaticMethod("onActionCancel", &JSGesture::JsHandlerOnActionCancel);
834 JSClass<JSLongPressGesture>::StaticMethod("onActionUpdate", &JSGesture::JsHandlerOnActionUpdate);
835 JSClass<JSLongPressGesture>::Bind(globalObj);
836
837 JSClass<JSPanGesture>::Declare("PanGesture");
838 JSClass<JSPanGesture>::StaticMethod("create", &JSPanGesture::Create, opt);
839 JSClass<JSPanGesture>::StaticMethod("tag", &JSGesture::SetTag, opt);
840 JSClass<JSPanGesture>::StaticMethod("allowedTypes", &JSGesture::SetAllowedTypes);
841 JSClass<JSPanGesture>::StaticMethod("pop", &JSGesture::Pop);
842 JSClass<JSPanGesture>::StaticMethod("onActionStart", &JSGesture::JsHandlerOnActionStart);
843 JSClass<JSPanGesture>::StaticMethod("onActionUpdate", &JSGesture::JsHandlerOnActionUpdate);
844 JSClass<JSPanGesture>::StaticMethod("onActionEnd", &JSGesture::JsHandlerOnActionEnd);
845 JSClass<JSPanGesture>::StaticMethod("onActionCancel", &JSGesture::JsHandlerOnActionCancel);
846 JSClass<JSPanGesture>::Bind(globalObj);
847
848 JSClass<JSSwipeGesture>::Declare("SwipeGesture");
849 JSClass<JSSwipeGesture>::StaticMethod("create", &JSSwipeGesture::Create, opt);
850 JSClass<JSSwipeGesture>::StaticMethod("tag", &JSGesture::SetTag, opt);
851 JSClass<JSSwipeGesture>::StaticMethod("allowedTypes", &JSGesture::SetAllowedTypes);
852 JSClass<JSSwipeGesture>::StaticMethod("pop", &JSGesture::Pop);
853 JSClass<JSSwipeGesture>::StaticMethod("onAction", &JSGesture::JsHandlerOnAction);
854 JSClass<JSSwipeGesture>::Bind(globalObj);
855
856 JSClass<JSPinchGesture>::Declare("PinchGesture");
857 JSClass<JSPinchGesture>::StaticMethod("create", &JSPinchGesture::Create, opt);
858 JSClass<JSPinchGesture>::StaticMethod("tag", &JSGesture::SetTag, opt);
859 JSClass<JSPinchGesture>::StaticMethod("allowedTypes", &JSGesture::SetAllowedTypes);
860 JSClass<JSPinchGesture>::StaticMethod("pop", &JSGesture::Pop);
861 JSClass<JSPinchGesture>::StaticMethod("onActionStart", &JSGesture::JsHandlerOnActionStart);
862 JSClass<JSPinchGesture>::StaticMethod("onActionUpdate", &JSGesture::JsHandlerOnActionUpdate);
863 JSClass<JSPinchGesture>::StaticMethod("onActionEnd", &JSGesture::JsHandlerOnActionEnd);
864 JSClass<JSPinchGesture>::StaticMethod("onActionCancel", &JSGesture::JsHandlerOnActionCancel);
865 JSClass<JSPinchGesture>::Bind(globalObj);
866
867 JSClass<JSRotationGesture>::Declare("RotationGesture");
868 JSClass<JSRotationGesture>::StaticMethod("create", &JSRotationGesture::Create, opt);
869 JSClass<JSRotationGesture>::StaticMethod("tag", &JSGesture::SetTag, opt);
870 JSClass<JSRotationGesture>::StaticMethod("allowedTypes", &JSGesture::SetAllowedTypes);
871 JSClass<JSRotationGesture>::StaticMethod("pop", &JSGesture::Pop);
872 JSClass<JSRotationGesture>::StaticMethod("onActionStart", &JSGesture::JsHandlerOnActionStart);
873 JSClass<JSRotationGesture>::StaticMethod("onActionUpdate", &JSGesture::JsHandlerOnActionUpdate);
874 JSClass<JSRotationGesture>::StaticMethod("onActionEnd", &JSGesture::JsHandlerOnActionEnd);
875 JSClass<JSRotationGesture>::StaticMethod("onActionCancel", &JSGesture::JsHandlerOnActionCancel);
876 JSClass<JSRotationGesture>::Bind(globalObj);
877
878 JSClass<JSGestureGroup>::Declare("GestureGroup");
879 JSClass<JSGestureGroup>::StaticMethod("create", &JSGestureGroup::Create, opt);
880 JSClass<JSGestureGroup>::StaticMethod("pop", &JSGesture::Pop);
881 JSClass<JSGestureGroup>::StaticMethod("onCancel", &JSGesture::JsHandlerOnActionCancel);
882 JSClass<JSGestureGroup>::Bind<>(globalObj);
883
884 JSClass<JSTimeoutGesture>::Declare("TimeoutGesture");
885 JSClass<JSTimeoutGesture>::StaticMethod("create", &JSTimeoutGesture::Create, opt);
886 JSClass<JSTimeoutGesture>::StaticMethod("pop", &JSGesture::Pop);
887
888 JSClass<JSTimeoutGesture>::Bind<>(globalObj);
889 }
890
Create(const JSCallbackInfo & args)891 void JSTimeoutGesture::Create(const JSCallbackInfo& args)
892 {
893 auto jsGesture = args[0];
894 if (!jsGesture->IsNumber()) {
895 return;
896 }
897
898 RefPtr<GestureProcessor> gestureProcessor;
899 gestureProcessor = TimeoutGestureModel::GetInstance()->GetGestureProcessor();
900 auto gesture = AceType::MakeRefPtr<TimeoutGesture>(std::chrono::duration<float>(jsGesture->ToNumber<float>()));
901 gestureProcessor->PushGesture(gesture);
902 }
903
JSBind(BindingTarget globalObj)904 void JSTimeoutGesture::JSBind(BindingTarget globalObj)
905 {
906 JSClass<JSTimeoutGesture>::Declare("TimeoutGesture");
907 MethodOptions opt = MethodOptions::NONE;
908 JSClass<JSTimeoutGesture>::StaticMethod("create", &JSTimeoutGesture::Create, opt);
909 JSClass<JSTimeoutGesture>::StaticMethod("pop", &JSGesture::Pop);
910
911 JSClass<JSTimeoutGesture>::Bind<>(globalObj);
912 }
913 }; // namespace OHOS::Ace::Framework
914