• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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