1 /*
2 * Copyright (c) 2021-2022 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 "core/components_ng/base/observer_handler.h"
17 #include "core/components_ng/gestures/recognizers/pinch_recognizer.h"
18 #include "core/components_ng/manager/event/json_child_report.h"
19 #include "core/common/reporter/reporter.h"
20 #include "core/components_ng/event/event_constants.h"
21 #include "core/components_ng/manager/event/json_report.h"
22
23 #include "base/ressched/ressched_report.h"
24 #include "core/event/ace_events.h"
25
26 namespace OHOS::Ace::NG {
27
28 namespace {
29
30 constexpr int32_t MAX_PINCH_FINGERS = 5;
31 constexpr int32_t DEFAULT_PINCH_FINGERS = 2;
32 constexpr Dimension DEFAULT_PINCH_DISTANCE = Dimension(5.0, DimensionUnit::VP);
33 constexpr double SCALE_PER_AXIS_EVENT = 0.1f;
34
35 } // namespace
36
PinchRecognizer(int32_t fingers,double distance,bool isLimitFingerCount)37 PinchRecognizer::PinchRecognizer(int32_t fingers, double distance, bool isLimitFingerCount)
38 : MultiFingersRecognizer(fingers, isLimitFingerCount), distance_(distance)
39 {
40 if (fingers_ > MAX_PINCH_FINGERS || fingers_ < DEFAULT_PINCH_FINGERS) {
41 fingers_ = DEFAULT_PINCH_FINGERS;
42 }
43 if (distance_ <= 0) {
44 distance_ = DEFAULT_PINCH_DISTANCE.ConvertToPx();
45 }
46 }
47
OnAccepted()48 void PinchRecognizer::OnAccepted()
49 {
50 int64_t acceptTime = GetSysTimestamp();
51 int64_t inputTime = acceptTime;
52 if (firstInputTime_.has_value()) {
53 inputTime = static_cast<int64_t>(firstInputTime_.value().time_since_epoch().count());
54 }
55 if (SystemProperties::GetTraceInputEventEnabled()) {
56 ACE_SCOPED_TRACE("UserEvent InputTime:%lld AcceptTime:%lld InputType:PinchGesture",
57 static_cast<long long>(inputTime), static_cast<long long>(acceptTime));
58 }
59
60 auto node = GetAttachedNode().Upgrade();
61 TAG_LOGI(AceLogTag::ACE_INPUTKEYFLOW, "PINCH RACC, T: %{public}s",
62 node ? node->GetTag().c_str() : "null");
63 ResSchedReport::GetInstance().ResSchedDataReport("click");
64 lastRefereeState_ = refereeState_;
65 refereeState_ = RefereeState::SUCCEED;
66 isLastPinchFinished_ = false;
67 TouchEvent touchPoint = {};
68 if (!touchPoints_.empty()) {
69 touchPoint = touchPoints_.begin()->second;
70 }
71 localMatrix_ = NGGestureRecognizer::GetTransformMatrix(GetAttachedNode(), false,
72 isPostEventResult_, touchPoint.postEventNodeId);
73 SendCallbackMsg(onActionStart_, GestureCallbackType::START);
74 isNeedResetVoluntarily_ = false;
75 }
76
OnRejected()77 void PinchRecognizer::OnRejected()
78 {
79 if (refereeState_ == RefereeState::SUCCEED) {
80 return;
81 }
82 SendRejectMsg();
83 lastRefereeState_ = refereeState_;
84 refereeState_ = RefereeState::FAIL;
85 firstInputTime_.reset();
86 }
87
IsCtrlBeingPressed(const AxisEvent & event)88 bool PinchRecognizer::IsCtrlBeingPressed(const AxisEvent& event)
89 {
90 return std::any_of(event.pressedCodes.begin(), event.pressedCodes.end(),
91 [](const KeyCode& code) { return code == KeyCode::KEY_CTRL_LEFT || code == KeyCode::KEY_CTRL_RIGHT; });
92 }
93
HandleTouchDownEvent(const TouchEvent & event)94 void PinchRecognizer::HandleTouchDownEvent(const TouchEvent& event)
95 {
96 extraInfo_ = "";
97 if (touchPoints_.size() == 1 && refereeState_ == RefereeState::FAIL) {
98 lastRefereeState_ = RefereeState::READY;
99 refereeState_ = RefereeState::READY;
100 }
101 touchPoints_[event.id] = event;
102 if (!firstInputTime_.has_value()) {
103 firstInputTime_ = event.time;
104 }
105
106 if (static_cast<int32_t>(activeFingers_.size()) >= fingers_) {
107 return;
108 }
109
110 if (fingersId_.find(event.id) == fingersId_.end()) {
111 fingersId_.insert(event.id);
112 }
113 activeFingers_.emplace_back(event.id);
114 lastTouchEvent_ = event;
115
116 if (static_cast<int32_t>(activeFingers_.size()) >= fingers_ && refereeState_ != RefereeState::FAIL) {
117 initialDev_ = ComputeAverageDeviation();
118 pinchCenter_ = ComputePinchCenter();
119 lastRefereeState_ = refereeState_;
120 refereeState_ = RefereeState::DETECTING;
121 }
122 }
123
HandleTouchDownEvent(const AxisEvent & event)124 void PinchRecognizer::HandleTouchDownEvent(const AxisEvent& event)
125 {
126 if (!firstInputTime_.has_value()) {
127 firstInputTime_ = event.time;
128 }
129 if (event.isRotationEvent) {
130 return;
131 }
132 touchPoints_[event.id] = TouchEvent();
133 UpdateTouchPointWithAxisEvent(event);
134 lastAxisEvent_ = event;
135 if (IsRefereeFinished()) {
136 return;
137 }
138 if (refereeState_ == RefereeState::READY &&
139 (NearEqual(event.pinchAxisScale, 1.0) ||
140 (IsCtrlBeingPressed(event) && event.sourceTool != SourceTool::TOUCHPAD))) {
141 scale_ = 1.0f;
142 pinchCenter_ = Offset(event.x, event.y);
143 lastRefereeState_ = refereeState_;
144 refereeState_ = RefereeState::DETECTING;
145 }
146 }
147
HandleTouchUpEvent(const TouchEvent & event)148 void PinchRecognizer::HandleTouchUpEvent(const TouchEvent& event)
149 {
150 if (fingersId_.find(event.id) != fingersId_.end()) {
151 fingersId_.erase(event.id);
152 }
153 if (fingersId_.empty()) {
154 isLastPinchFinished_ = true;
155 }
156 if (isNeedResetVoluntarily_ && currentFingers_ == 1) {
157 ResetStateVoluntarily();
158 isNeedResetVoluntarily_ = false;
159 activeFingers_.remove(event.id);
160 return;
161 }
162 if (!IsActiveFinger(event.id)) {
163 return;
164 }
165
166 touchPoints_[event.id] = event;
167 extraInfo_ = "activeSize: " + std::to_string(static_cast<int32_t>(activeFingers_.size()));
168 if (static_cast<int32_t>(activeFingers_.size()) < fingers_ && refereeState_ != RefereeState::SUCCEED) {
169 extraInfo_ += "activeFinger size not satisify.";
170 Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
171 activeFingers_.remove(event.id);
172 return;
173 }
174
175 lastTouchEvent_ = event;
176 if ((refereeState_ != RefereeState::SUCCEED) && (refereeState_ != RefereeState::FAIL)) {
177 extraInfo_ += "refereeState not satisfy.";
178 Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
179 activeFingers_.remove(event.id);
180 return;
181 }
182
183 if (refereeState_ == RefereeState::SUCCEED && static_cast<int32_t>(activeFingers_.size()) == fingers_) {
184 pinchCenter_ = ComputePinchCenter();
185 SendCallbackMsg(onActionEnd_, GestureCallbackType::END);
186 int64_t overTime = GetSysTimestamp();
187 int64_t inputTime = overTime;
188 if (firstInputTime_.has_value()) {
189 inputTime = static_cast<int64_t>(firstInputTime_.value().time_since_epoch().count());
190 }
191 if (SystemProperties::GetTraceInputEventEnabled()) {
192 ACE_SCOPED_TRACE("UserEvent InputTime:%lld OverTime:%lld InputType:PinchGesture",
193 static_cast<long long>(inputTime), static_cast<long long>(overTime));
194 }
195 firstInputTime_.reset();
196 isNeedResetVoluntarily_ = true;
197 }
198 activeFingers_.remove(event.id);
199 }
200
HandleTouchUpEvent(const AxisEvent & event)201 void PinchRecognizer::HandleTouchUpEvent(const AxisEvent& event)
202 {
203 // if axisEvent received rotateEvent, no need to active Pinch recognizer.
204 if (isPinchEnd_ || event.isRotationEvent) {
205 return;
206 }
207 UpdateTouchPointWithAxisEvent(event);
208 lastAxisEvent_ = event;
209 if ((refereeState_ != RefereeState::SUCCEED) && (refereeState_ != RefereeState::FAIL)) {
210 Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
211 return;
212 }
213 if (refereeState_ == RefereeState::SUCCEED) {
214 SendCallbackMsg(onActionEnd_, GestureCallbackType::END);
215 isPinchEnd_ = true;
216 int64_t overTime = GetSysTimestamp();
217 int64_t inputTime = overTime;
218 if (firstInputTime_.has_value()) {
219 inputTime = static_cast<int64_t>(firstInputTime_.value().time_since_epoch().count());
220 }
221 if (SystemProperties::GetTraceInputEventEnabled()) {
222 ACE_SCOPED_TRACE("UserEvent InputTime:%lld OverTime:%lld InputType:PinchGesture",
223 static_cast<long long>(inputTime), static_cast<long long>(overTime));
224 }
225 firstInputTime_.reset();
226 }
227 }
228
HandleTouchMoveEvent(const TouchEvent & event)229 void PinchRecognizer::HandleTouchMoveEvent(const TouchEvent& event)
230 {
231 touchPoints_[event.id] = event;
232 if (!IsActiveFinger(event.id)) {
233 return;
234 }
235
236 lastTouchEvent_ = event;
237 currentDev_ = ComputeAverageDeviation();
238 time_ = event.time;
239
240 if (static_cast<int32_t>(touchPoints_.size()) < fingers_ ||
241 static_cast<int32_t>(activeFingers_.size()) < fingers_) {
242 return;
243 }
244 if (refereeState_ == RefereeState::DETECTING) {
245 if (GreatOrEqual(fabs(currentDev_ - initialDev_), distance_)) {
246 scale_ = currentDev_ / initialDev_;
247 if (CheckLimitFinger()) {
248 extraInfo_ += " isLFC: " + std::to_string(isLimitFingerCount_);
249 return;
250 }
251 auto onGestureJudgeBeginResult = TriggerGestureJudgeCallback();
252 if (onGestureJudgeBeginResult == GestureJudgeResult::REJECT) {
253 Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
254 return;
255 }
256 if (!isLastPinchFinished_) {
257 OnAccepted();
258 } else {
259 Adjudicate(AceType::Claim(this), GestureDisposal::ACCEPT);
260 }
261 }
262 } else if (refereeState_ == RefereeState::SUCCEED) {
263 scale_ = currentDev_ / initialDev_;
264 pinchCenter_ = ComputePinchCenter();
265 if (static_cast<int32_t>(touchPoints_.size()) > fingers_ && isLimitFingerCount_) {
266 return;
267 }
268 if (isFlushTouchEventsEnd_) {
269 SendCallbackMsg(onActionUpdate_, GestureCallbackType::UPDATE);
270 }
271 }
272 }
273
OnFlushTouchEventsBegin()274 void PinchRecognizer::OnFlushTouchEventsBegin()
275 {
276 isFlushTouchEventsEnd_ = false;
277 }
278
OnFlushTouchEventsEnd()279 void PinchRecognizer::OnFlushTouchEventsEnd()
280 {
281 isFlushTouchEventsEnd_ = true;
282 }
283
HandleTouchMoveEvent(const AxisEvent & event)284 void PinchRecognizer::HandleTouchMoveEvent(const AxisEvent& event)
285 {
286 if (event.isRotationEvent || isPinchEnd_) {
287 return;
288 }
289 if (ProcessAxisAbnormalCondition(event)) {
290 return;
291 }
292 UpdateTouchPointWithAxisEvent(event);
293 lastTouchEvent_ = touchPoints_[event.id];
294 time_ = event.time;
295 lastAxisEvent_ = event;
296 if (refereeState_ == RefereeState::DETECTING || refereeState_ == RefereeState::SUCCEED) {
297 if (event.pinchAxisScale != 0.0) {
298 scale_ = event.pinchAxisScale;
299 } else {
300 if (GreatNotEqual(event.verticalAxis, 0.0) || GreatNotEqual(event.horizontalAxis, 0.0)) {
301 scale_ -= SCALE_PER_AXIS_EVENT;
302 } else if (LessNotEqual(event.verticalAxis, 0.0) || LessNotEqual(event.horizontalAxis, 0)) {
303 scale_ += SCALE_PER_AXIS_EVENT;
304 }
305 if (LessNotEqual(scale_, 0.0)) {
306 scale_ = 0.0;
307 }
308 }
309 if (refereeState_ == RefereeState::DETECTING) {
310 auto onGestureJudgeBeginResult = TriggerGestureJudgeCallback();
311 if (onGestureJudgeBeginResult == GestureJudgeResult::REJECT) {
312 Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
313 return;
314 }
315 Adjudicate(AceType::Claim(this), GestureDisposal::ACCEPT);
316 }
317 SendCallbackMsg(onActionUpdate_, GestureCallbackType::UPDATE);
318 }
319 }
320
HandleTouchCancelEvent(const TouchEvent & event)321 void PinchRecognizer::HandleTouchCancelEvent(const TouchEvent& event)
322 {
323 extraInfo_ += "cancel received.";
324 if (!IsActiveFinger(event.id)) {
325 return;
326 }
327 touchPoints_[event.id] = event;
328 if ((refereeState_ != RefereeState::SUCCEED) && (refereeState_ != RefereeState::FAIL)) {
329 Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
330 return;
331 }
332
333 if (refereeState_ == RefereeState::SUCCEED && static_cast<int32_t>(activeFingers_.size()) == fingers_) {
334 SendCallbackMsg(onActionCancel_, GestureCallbackType::CANCEL);
335 lastRefereeState_ = RefereeState::READY;
336 refereeState_ = RefereeState::READY;
337 } else if (refereeState_ == RefereeState::SUCCEED) {
338 TAG_LOGI(AceLogTag::ACE_INPUTKEYFLOW,
339 "PinchRecognizer activeFingers size not equal fingers_, not send cancel callback.");
340 }
341 }
342
HandleTouchCancelEvent(const AxisEvent & event)343 void PinchRecognizer::HandleTouchCancelEvent(const AxisEvent& event)
344 {
345 extraInfo_ += "cancel received.";
346 UpdateTouchPointWithAxisEvent(event);
347 if ((refereeState_ != RefereeState::SUCCEED) && (refereeState_ != RefereeState::FAIL)) {
348 Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
349 return;
350 }
351
352 if (refereeState_ == RefereeState::SUCCEED) {
353 SendCallbackMsg(onActionCancel_, GestureCallbackType::CANCEL);
354 }
355 }
356
ComputeAverageDeviation()357 double PinchRecognizer::ComputeAverageDeviation()
358 {
359 // compute the coordinate of focal point
360 double sumOfX = 0.0;
361 double sumOfY = 0.0;
362 for (auto& id : activeFingers_) {
363 sumOfX = sumOfX + touchPoints_[id].x;
364 sumOfY = sumOfY + touchPoints_[id].y;
365 }
366 double focalX = sumOfX / fingers_;
367 double focalY = sumOfY / fingers_;
368
369 // compute average deviation
370 double devX = 0.0;
371 double devY = 0.0;
372 for (auto& id : activeFingers_) {
373 devX = devX + fabs(touchPoints_[id].x - focalX);
374 devY = devY + fabs(touchPoints_[id].y - focalY);
375 }
376 double aveDevX = devX / fingers_;
377 double aveDevY = devY / fingers_;
378
379 // compute zoom distance
380 double zoomDistance = sqrt(pow(aveDevX, 2) + pow(aveDevY, 2));
381
382 return zoomDistance;
383 }
384
ComputePinchCenter()385 Offset PinchRecognizer::ComputePinchCenter()
386 {
387 if (touchPoints_.empty()) {
388 return Offset();
389 }
390 double sumOfX = 0.0;
391 double sumOfY = 0.0;
392 for (auto& id : activeFingers_) {
393 sumOfX = sumOfX + touchPoints_[id].x;
394 sumOfY = sumOfY + touchPoints_[id].y;
395 }
396 double focalX = sumOfX / fingers_;
397 double focalY = sumOfY / fingers_;
398
399 PointF localPoint(focalX, focalY);
400 TransformForRecognizer(localPoint, GetAttachedNode(), false,
401 isPostEventResult_, touchPoints_.begin()->second.postEventNodeId);
402 Offset pinchCenter = Offset(localPoint.GetX(), localPoint.GetY());
403
404 return pinchCenter;
405 }
406
OnResetStatus()407 void PinchRecognizer::OnResetStatus()
408 {
409 MultiFingersRecognizer::OnResetStatus();
410 initialDev_ = 0.0;
411 currentDev_ = 0.0;
412 scale_ = 1.0;
413 isFlushTouchEventsEnd_ = false;
414 isPinchEnd_ = false;
415 isLastPinchFinished_ = true;
416 localMatrix_.clear();
417 pinchCenter_ = Offset();
418 }
419
SendCallbackMsg(const std::unique_ptr<GestureEventFunc> & callback,GestureCallbackType type)420 void PinchRecognizer::SendCallbackMsg(const std::unique_ptr<GestureEventFunc>& callback, GestureCallbackType type)
421 {
422 std::string callbackName = GetCallbackName(callback);
423 ACE_SCOPED_TRACE("PinchRecognizer %s, currentDev_: %f", callbackName.c_str(), currentDev_);
424 if (gestureInfo_ && gestureInfo_->GetDisposeTag()) {
425 return;
426 }
427 if (callback && *callback) {
428 GestureEvent info;
429 info.SetTimeStamp(time_);
430 UpdateFingerListInfo();
431 info.SetFingerList(fingerList_);
432 info.SetScale(scale_);
433 info.SetPinchCenter(pinchCenter_);
434 info.SetDeviceId(deviceId_);
435 info.SetSourceDevice(deviceType_);
436 info.SetTarget(GetEventTarget().value_or(EventTarget()));
437 info.SetGestureTypeName(GestureTypeName::PINCH_GESTURE);
438 info.SetForce(lastTouchEvent_.force);
439 if (lastTouchEvent_.tiltX.has_value()) {
440 info.SetTiltX(lastTouchEvent_.tiltX.value());
441 }
442 if (lastTouchEvent_.tiltY.has_value()) {
443 info.SetTiltY(lastTouchEvent_.tiltY.value());
444 }
445 if (lastTouchEvent_.rollAngle.has_value()) {
446 info.SetRollAngle(lastTouchEvent_.rollAngle.value());
447 }
448 if (inputEventType_ == InputEventType::AXIS) {
449 info.SetVerticalAxis(lastAxisEvent_.verticalAxis);
450 info.SetHorizontalAxis(lastAxisEvent_.horizontalAxis);
451 info.SetSourceTool(lastAxisEvent_.sourceTool);
452 info.SetPressedKeyCodes(lastAxisEvent_.pressedCodes);
453 info.CopyConvertInfoFrom(lastAxisEvent_.convertInfo);
454 info.SetTargetDisplayId(lastAxisEvent_.targetDisplayId);
455 } else {
456 info.CopyConvertInfoFrom(lastTouchEvent_.convertInfo);
457 info.SetSourceTool(lastTouchEvent_.sourceTool);
458 info.SetPressedKeyCodes(lastTouchEvent_.pressedKeyCodes_);
459 info.SetTargetDisplayId(lastTouchEvent_.targetDisplayId);
460 }
461 info.SetPointerEvent(lastPointEvent_);
462 info.SetInputEventType(inputEventType_);
463 // callback may be overwritten in its invoke so we copy it first
464 auto callbackFunction = *callback;
465 HandleGestureAccept(info, type, GestureListenerType::PINCH);
466 callbackFunction(info);
467 HandleReports(info, type);
468 }
469 }
470
HandleReports(const GestureEvent & info,GestureCallbackType type)471 void PinchRecognizer::HandleReports(const GestureEvent& info, GestureCallbackType type)
472 {
473 if (type == GestureCallbackType::ACTION || type == GestureCallbackType::UPDATE) {
474 return;
475 }
476 auto frameNode = GetAttachedNode().Upgrade();
477 CHECK_NULL_VOID(frameNode);
478 PinchJsonReport pinchReport;
479 pinchReport.SetCallbackType(type);
480 pinchReport.SetGestureType(GetRecognizerType());
481 pinchReport.SetId(frameNode->GetId());
482 pinchReport.SetFingerList(info.GetFingerList());
483 pinchReport.SetScale(info.GetScale());
484 Reporter::GetInstance().HandleUISessionReporting(pinchReport);
485 }
486
TriggerGestureJudgeCallback()487 GestureJudgeResult PinchRecognizer::TriggerGestureJudgeCallback()
488 {
489 auto targetComponent = GetTargetComponent();
490 CHECK_NULL_RETURN(targetComponent, GestureJudgeResult::CONTINUE);
491 auto gestureRecognizerJudgeFunc = targetComponent->GetOnGestureRecognizerJudgeBegin();
492 auto callback = targetComponent->GetOnGestureJudgeBeginCallback();
493 if (!callback && !gestureRecognizerJudgeFunc) {
494 return GestureJudgeResult::CONTINUE;
495 }
496 auto info = std::make_shared<PinchGestureEvent>();
497 info->SetTimeStamp(time_);
498 info->SetDeviceId(deviceId_);
499 UpdateFingerListInfo();
500 info->SetFingerList(fingerList_);
501 info->SetScale(scale_);
502 info->SetPinchCenter(pinchCenter_);
503 info->SetSourceDevice(deviceType_);
504 info->SetTarget(GetEventTarget().value_or(EventTarget()));
505 info->SetForce(lastTouchEvent_.force);
506 if (gestureInfo_) {
507 gestureInfo_->SetInputEventType(inputEventType_);
508 }
509 if (lastTouchEvent_.tiltX.has_value()) {
510 info->SetTiltX(lastTouchEvent_.tiltX.value());
511 }
512 if (lastTouchEvent_.tiltY.has_value()) {
513 info->SetTiltY(lastTouchEvent_.tiltY.value());
514 }
515 if (lastTouchEvent_.rollAngle.has_value()) {
516 info->SetRollAngle(lastTouchEvent_.rollAngle.value());
517 }
518 info->SetSourceTool(lastTouchEvent_.sourceTool);
519 info->SetRawInputEventType(inputEventType_);
520 info->SetRawInputEvent(lastPointEvent_);
521 info->SetRawInputDeviceId(deviceId_);
522 if (inputEventType_ == InputEventType::AXIS) {
523 info->SetPressedKeyCodes(lastAxisEvent_.pressedCodes);
524 info->SetTargetDisplayId(lastAxisEvent_.targetDisplayId);
525 } else {
526 info->SetTargetDisplayId(lastTouchEvent_.targetDisplayId);
527 info->SetPressedKeyCodes(lastTouchEvent_.pressedKeyCodes_);
528 }
529 if (gestureRecognizerJudgeFunc) {
530 return gestureRecognizerJudgeFunc(info, Claim(this), responseLinkRecognizer_);
531 }
532 return callback(gestureInfo_, info);
533 }
534
ReconcileFrom(const RefPtr<NGGestureRecognizer> & recognizer)535 bool PinchRecognizer::ReconcileFrom(const RefPtr<NGGestureRecognizer>& recognizer)
536 {
537 RefPtr<PinchRecognizer> curr = AceType::DynamicCast<PinchRecognizer>(recognizer);
538 if (!curr) {
539 ResetStatus();
540 return false;
541 }
542
543 if (curr->fingers_ != fingers_ || curr->distance_ != distance_ || curr->priorityMask_ != priorityMask_) {
544 if (refereeState_ == RefereeState::SUCCEED && static_cast<int32_t>(activeFingers_.size()) == fingers_) {
545 SendCallbackMsg(onActionCancel_, GestureCallbackType::CANCEL);
546 }
547 ResetStatus();
548 return false;
549 }
550 isLimitFingerCount_ = curr->isLimitFingerCount_;
551
552 onActionStart_ = std::move(curr->onActionStart_);
553 onActionUpdate_ = std::move(curr->onActionUpdate_);
554 onActionEnd_ = std::move(curr->onActionEnd_);
555 onActionCancel_ = std::move(curr->onActionCancel_);
556 ReconcileGestureInfoFrom(recognizer);
557 return true;
558 }
559
Dump() const560 RefPtr<GestureSnapshot> PinchRecognizer::Dump() const
561 {
562 RefPtr<GestureSnapshot> info = NGGestureRecognizer::Dump();
563 std::stringstream oss;
564 oss << "distance: " << distance_ << ", "
565 << "fingers: " << fingers_ << ", "
566 << DumpGestureInfo();
567 info->customInfo = oss.str();
568 return info;
569 }
570
ProcessAxisAbnormalCondition(const AxisEvent & event)571 bool PinchRecognizer::ProcessAxisAbnormalCondition(const AxisEvent& event)
572 {
573 if (NearZero(event.pinchAxisScale) && (!IsCtrlBeingPressed(event) || event.sourceTool == SourceTool::TOUCHPAD)) {
574 if (ProcessAxisReject()) {
575 return true;
576 }
577 }
578 return false;
579 }
580
ProcessAxisReject()581 bool PinchRecognizer::ProcessAxisReject()
582 {
583 if (refereeState_ == RefereeState::DETECTING) {
584 Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
585 return true;
586 }
587 if (refereeState_ == RefereeState::SUCCEED) {
588 lastRefereeState_ = RefereeState::READY;
589 refereeState_ = RefereeState::READY;
590 SendCallbackMsg(onActionEnd_, GestureCallbackType::END);
591 isPinchEnd_ = true;
592 return true;
593 }
594 return false;
595 }
596
597 } // namespace OHOS::Ace::NG
598