• 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/event/event_constants.h"
18 #include "core/components_ng/gestures/recognizers/pan_recognizer.h"
19 #include "core/components_ng/manager/event/json_child_report.h"
20 #include "core/common/reporter/reporter.h"
21 #include "core/components_ng/manager/event/json_report.h"
22 
23 #include "base/perfmonitor/perf_monitor.h"
24 #include "core/pipeline_ng/pipeline_context.h"
25 
26 namespace OHOS::Ace::NG {
27 
28 namespace {
29 
30 constexpr int32_t MAX_PAN_FINGERS = 10;
31 constexpr int32_t DEFAULT_PAN_FINGERS = 1;
32 constexpr int32_t AXIS_PAN_FINGERS = 1;
33 constexpr float MIN_SPEED_THRESHOLD = 500.0f;
34 constexpr float TOUCHPAD_STILL_THRESHOLD = 0.1;
35 
36 } // namespace
37 
ForceCleanRecognizer()38 void PanRecognizer::ForceCleanRecognizer()
39 {
40     MultiFingersRecognizer::ForceCleanRecognizer();
41     averageDistance_.Reset();
42     touchPointsDistance_.clear();
43     localMatrix_.clear();
44     isStartTriggered_ = false;
45 }
46 
PanRecognizer(int32_t fingers,const PanDirection & direction,double distance,bool isLimitFingerCount)47 PanRecognizer::PanRecognizer(int32_t fingers, const PanDirection& direction, double distance, bool isLimitFingerCount)
48     : MultiFingersRecognizer(fingers, isLimitFingerCount), direction_(direction), distance_(distance),
49     mouseDistance_(distance), newFingers_(fingers_), newDistance_(distance_), newDirection_(direction_)
50 {
51     distanceMap_[SourceTool::UNKNOWN] = Dimension(
52         Dimension(distance_, DimensionUnit::PX).ConvertToVp(), DimensionUnit::VP);
53     newDistanceMap_[SourceTool::UNKNOWN] = Dimension(
54         Dimension(distance_, DimensionUnit::PX).ConvertToVp(), DimensionUnit::VP);
55     panVelocity_.SetDirection(direction_.type);
56     if (fingers_ > MAX_PAN_FINGERS || fingers_ < DEFAULT_PAN_FINGERS) {
57         fingers_ = DEFAULT_PAN_FINGERS;
58     }
59 }
60 
PanRecognizer(int32_t fingers,const PanDirection & direction,const PanDistanceMap & distanceMap,bool isLimitFingerCount)61 PanRecognizer::PanRecognizer(
62     int32_t fingers, const PanDirection& direction, const PanDistanceMap& distanceMap, bool isLimitFingerCount)
63     : MultiFingersRecognizer(fingers, isLimitFingerCount), direction_(direction), newFingers_(fingers_),
64       newDirection_(direction_)
65 {
66     SetDistanceMap(distanceMap);
67     panVelocity_.SetDirection(direction_.type);
68     if (fingers_ > MAX_PAN_FINGERS || fingers_ < DEFAULT_PAN_FINGERS) {
69         fingers_ = DEFAULT_PAN_FINGERS;
70     }
71 }
72 
PanRecognizer(int32_t fingers,const PanDirection & direction,const PanDistanceMapDimension & distanceMap,bool isLimitFingerCount)73 PanRecognizer::PanRecognizer(int32_t fingers, const PanDirection& direction,
74     const PanDistanceMapDimension& distanceMap, bool isLimitFingerCount)
75     : MultiFingersRecognizer(fingers, isLimitFingerCount), direction_(direction), newFingers_(fingers_),
76       newDirection_(direction_), distanceMap_(distanceMap), newDistanceMap_(distanceMap)
77 {
78     panVelocity_.SetDirection(direction_.type);
79     if (fingers_ > MAX_PAN_FINGERS || fingers_ < DEFAULT_PAN_FINGERS) {
80         fingers_ = DEFAULT_PAN_FINGERS;
81     }
82 }
83 
CreateGestureFromRecognizer() const84 RefPtr<Gesture> PanRecognizer::CreateGestureFromRecognizer() const
85 {
86     return AceType::MakeRefPtr<PanGesture>(fingers_, direction_, distanceMap_, isLimitFingerCount_);
87 }
88 
ResetDistanceMap()89 void PanRecognizer::ResetDistanceMap()
90 {
91     for (auto& iter : distanceMap_) {
92         distanceMap_[iter.first] = LessNotEqual(iter.second.ConvertToPx(), 0.0) ? DEFAULT_PAN_DISTANCE : iter.second;
93     }
94     if (distanceMap_.find(SourceTool::UNKNOWN) == distanceMap_.end()) {
95         distanceMap_[SourceTool::UNKNOWN] = DEFAULT_PAN_DISTANCE;
96     }
97 }
98 
PanRecognizer(const RefPtr<PanGestureOption> & panGestureOption)99 PanRecognizer::PanRecognizer(const RefPtr<PanGestureOption>& panGestureOption) : panGestureOption_(panGestureOption)
100 {
101     uint32_t directNum = panGestureOption->GetDirection().type;
102     int32_t fingersNumber = panGestureOption->GetFingers();
103     bool isLimitFingerCount = panGestureOption->GetIsLimitFingerCount();
104 
105     fingers_ = fingersNumber;
106     isLimitFingerCount_ = isLimitFingerCount;
107     if (fingers_ > MAX_PAN_FINGERS || fingers_ < DEFAULT_PAN_FINGERS) {
108         fingers_ = DEFAULT_PAN_FINGERS;
109     }
110 
111     if (directNum >= PanDirection::NONE && directNum <= PanDirection::ALL) {
112         direction_.type = directNum;
113     }
114 
115     distanceMap_ = panGestureOption->GetPanDistanceMap();
116     ResetDistanceMap();
117     newDistanceMap_ = distanceMap_;
118     newFingers_ = fingers_;
119     newDirection_ = direction_;
120 
121     PanFingersFuncType changeFingers = [weak = AceType::WeakClaim(this)](int32_t fingers) {
122         auto panRecognizer = weak.Upgrade();
123         CHECK_NULL_VOID(panRecognizer);
124         panRecognizer->ChangeFingers(fingers);
125     };
126     onChangeFingers_ = OnPanFingersFunc(changeFingers);
127     panGestureOption_->SetOnPanFingersId(onChangeFingers_);
128 
129     PanDirectionFuncType changeDirection = [weak = AceType::WeakClaim(this)](const PanDirection& direction) {
130         auto panRecognizer = weak.Upgrade();
131         CHECK_NULL_VOID(panRecognizer);
132         panRecognizer->ChangeDirection(direction);
133     };
134     onChangeDirection_ = OnPanDirectionFunc(changeDirection);
135     panGestureOption_->SetOnPanDirectionId(onChangeDirection_);
136 
137     PanDistanceFuncType changeDistance = [weak = AceType::WeakClaim(this)](double distance) {
138         auto panRecognizer = weak.Upgrade();
139         CHECK_NULL_VOID(panRecognizer);
140         panRecognizer->ChangeDistance(distance);
141     };
142     onChangeDistance_ = OnPanDistanceFunc(changeDistance);
143     panGestureOption_->SetOnPanDistanceId(onChangeDistance_);
144 }
145 
OnAccepted()146 void PanRecognizer::OnAccepted()
147 {
148     int64_t acceptTime = GetSysTimestamp();
149     int64_t inputTime = acceptTime;
150     if (firstInputTime_.has_value()) {
151         inputTime = static_cast<int64_t>(firstInputTime_.value().time_since_epoch().count());
152     }
153     if (SystemProperties::GetTraceInputEventEnabled()) {
154         ACE_SCOPED_TRACE("UserEvent InputTime:%lld AcceptTime:%lld InputType:PanGesture",
155             static_cast<long long>(inputTime), static_cast<long long>(acceptTime));
156     }
157 
158     auto node = GetAttachedNode().Upgrade();
159     TAG_LOGI(AceLogTag::ACE_INPUTKEYFLOW,
160         "PAN RACC, T: %{public}s, DIS x %{public}f, y %{public}f",
161         node ? node->GetTag().c_str() : "null", averageDistance_.GetX(), averageDistance_.GetY());
162     lastRefereeState_ = refereeState_;
163     refereeState_ = RefereeState::SUCCEED;
164     TouchEvent touchPoint = {};
165     if (!touchPoints_.empty()) {
166         touchPoint = touchPoints_.begin()->second;
167     }
168     localMatrix_ = NGGestureRecognizer::GetTransformMatrix(GetAttachedNode(), false,
169         isPostEventResult_, touchPoint.postEventNodeId);
170     SendCallbackMsg(onActionStart_, GestureCallbackType::START);
171     isNeedResetVoluntarily_ = false;
172     // only report the pan gesture starting for touch event
173     DispatchPanStartedToPerf(lastTouchEvent_);
174     if (IsEnabled()) {
175         isStartTriggered_ = true;
176     }
177     SendCallbackMsg(onActionUpdate_, GestureCallbackType::UPDATE);
178     // if gesture is blocked by double click, recognizer will receive up before onAccepted
179     // in this case, recognizer need to send onActionEnd when onAccepted
180     if (isTouchEventFinished_) {
181         isStartTriggered_ = false;
182         SendCallbackMsg(onActionEnd_, GestureCallbackType::END);
183     }
184 }
185 
OnRejected()186 void PanRecognizer::OnRejected()
187 {
188     // fix griditem drag interrupted by click while pull moving
189     if (refereeState_ != RefereeState::SUCCEED) {
190         lastRefereeState_ = refereeState_;
191         refereeState_ = RefereeState::FAIL;
192     }
193     SendRejectMsg();
194     firstInputTime_.reset();
195 }
196 
UpdateTouchPointInVelocityTracker(const TouchEvent & touchEvent)197 void PanRecognizer::UpdateTouchPointInVelocityTracker(const TouchEvent& touchEvent)
198 {
199     auto updateTask = [this](const TouchEvent& event) {
200         bool end = event.type == TouchType::UP;
201         PointF windowPoint(event.x, event.y);
202         TouchEvent transformEvent = event;
203         auto container = Container::Current();
204         if (container && container->IsUIExtensionWindow()) {
205             auto historyEvent = Platform::GetTouchEventOriginOffset(end ? lastTouchEvent_ : event);
206             windowPoint.SetX(historyEvent.GetX());
207             windowPoint.SetY(historyEvent.GetY());
208             transformEvent.time = Platform::GetTouchEventOriginTimeStamp(end ? lastTouchEvent_ : event);
209         }
210         NGGestureRecognizer::Transform(windowPoint, GetAttachedNode(), false,
211             isPostEventResult_, event.postEventNodeId);
212 
213         transformEvent.x = windowPoint.GetX();
214         transformEvent.y = windowPoint.GetY();
215         panVelocity_.UpdateTouchPoint(event.id, transformEvent, end);
216     };
217     if (touchEvent.history.empty()) {
218         updateTask(touchEvent);
219         return;
220     }
221     for (const auto& historyEvent: touchEvent.history) {
222         updateTask(historyEvent);
223     }
224 }
225 
UpdateAxisPointInVelocityTracker(const AxisEvent & event,bool end)226 void PanRecognizer::UpdateAxisPointInVelocityTracker(const AxisEvent& event, bool end)
227 {
228     auto pesudoTouchEvent = TouchEvent();
229     pesudoTouchEvent.time = event.time;
230     auto revertAxisValue = event.ConvertToSummationAxisValue(lastAxisEvent_);
231     pesudoTouchEvent.x = revertAxisValue.first;
232     pesudoTouchEvent.y = revertAxisValue.second;
233     pesudoTouchEvent.sourceTool = event.sourceTool;
234     panVelocity_.UpdateTouchPoint(event.id, pesudoTouchEvent, end);
235     lastAxisEvent_ = event;
236     if (!end) {
237         lastAxisEvent_.horizontalAxis = pesudoTouchEvent.x;
238         lastAxisEvent_.verticalAxis = pesudoTouchEvent.y;
239     }
240 }
241 
HandleTouchDownEvent(const TouchEvent & event)242 void PanRecognizer::HandleTouchDownEvent(const TouchEvent& event)
243 {
244     extraInfo_ = "";
245     lastAction_ = inputEventType_ == InputEventType::TOUCH_SCREEN ? static_cast<int32_t>(TouchType::DOWN)
246                                                                   : static_cast<int32_t>(MouseAction::PRESS);
247     isTouchEventFinished_ = false;
248     if (!firstInputTime_.has_value()) {
249         firstInputTime_ = event.time;
250     }
251 
252     fingers_ = newFingers_;
253     distance_ = newDistance_;
254     direction_ = newDirection_;
255     distanceMap_ = newDistanceMap_;
256 
257     if (direction_.type == PanDirection::NONE) {
258         auto node = GetAttachedNode().Upgrade();
259         TAG_LOGI(AceLogTag::ACE_GESTURE, "Pan recognizer direction is none, "
260             "node tag = %{public}s, id = " SEC_PLD(%{public}s) ".",
261             node ? node->GetTag().c_str() : "null",
262             SEC_PARAM(node ? std::to_string(node->GetId()).c_str() : "invalid"));
263         extraInfo_ += "direction is NONE.";
264         Adjudicate(Claim(this), GestureDisposal::REJECT);
265         return;
266     }
267     if (event.sourceType == SourceType::MOUSE && !isAllowMouse_) {
268         Adjudicate(Claim(this), GestureDisposal::REJECT);
269         extraInfo_ += "mouse event is not allowed.";
270         return;
271     }
272 
273     if (fingersId_.find(event.id) == fingersId_.end()) {
274         fingersId_.insert(event.id);
275     }
276 
277     deviceId_ = event.deviceId;
278     deviceType_ = event.sourceType;
279     deviceTool_ = event.sourceTool;
280     lastTouchEvent_ = event;
281     touchPoints_[event.id] = event;
282     touchPointsDistance_[event.id] = Offset(0.0, 0.0);
283     auto fingerNum = static_cast<int32_t>(touchPoints_.size());
284 
285     if (fingerNum >= fingers_) {
286         if (refereeState_ == RefereeState::READY) {
287             panVelocity_.Reset(event.id);
288             UpdateTouchPointInVelocityTracker(event);
289             lastRefereeState_ = refereeState_;
290             refereeState_ = RefereeState::DETECTING;
291         } else {
292             TAG_LOGI(AceLogTag::ACE_GESTURE, "Pan gesture refereeState is not READY");
293         }
294     }
295     HandlePanExtAccept();
296 }
297 
HandleTouchDownEvent(const AxisEvent & event)298 void PanRecognizer::HandleTouchDownEvent(const AxisEvent& event)
299 {
300     extraInfo_ = "";
301     lastAction_ = static_cast<int32_t>(AxisAction::BEGIN);
302     isTouchEventFinished_ = false;
303     if (!firstInputTime_.has_value()) {
304         firstInputTime_ = event.time;
305     }
306     if (event.isRotationEvent) {
307         return;
308     }
309     fingers_ = newFingers_;
310     distance_ = newDistance_;
311     direction_ = newDirection_;
312     distanceMap_ = newDistanceMap_;
313 
314     if (fingers_ != AXIS_PAN_FINGERS) {
315         extraInfo_ += "fingers does not meet the requirements of the axis event.";
316         Adjudicate(Claim(this), GestureDisposal::REJECT);
317         return;
318     }
319 
320     if (direction_.type == PanDirection::NONE) {
321         extraInfo_ += "direction is NONE in axis case.";
322         Adjudicate(Claim(this), GestureDisposal::REJECT);
323         return;
324     }
325 
326     deviceId_ = event.deviceId;
327     deviceType_ = event.sourceType;
328     deviceTool_ = event.sourceTool;
329     lastAxisEvent_ = event;
330 
331     touchPoints_[event.id] = TouchEvent();
332     UpdateTouchPointWithAxisEvent(event);
333     panVelocity_.Reset(event.id);
334     auto pesudoTouchEvent = TouchEvent();
335     pesudoTouchEvent.time = event.time;
336     auto revertAxisValue = event.ConvertToSummationAxisValue(lastAxisEvent_);
337     pesudoTouchEvent.x = revertAxisValue.first;
338     pesudoTouchEvent.y = revertAxisValue.second;
339     pesudoTouchEvent.sourceTool = event.sourceTool;
340     panVelocity_.UpdateTouchPoint(event.id, pesudoTouchEvent, false);
341     lastRefereeState_ = refereeState_;
342     refereeState_ = RefereeState::DETECTING;
343 }
344 
HandleTouchUpEvent(const TouchEvent & event)345 void PanRecognizer::HandleTouchUpEvent(const TouchEvent& event)
346 {
347     extraInfo_ = "currentFingers: " + std::to_string(currentFingers_) + " fingers: " + std::to_string(fingers_);
348     lastAction_ = inputEventType_ == InputEventType::TOUCH_SCREEN ? static_cast<int32_t>(TouchType::UP)
349                                                                   : static_cast<int32_t>(MouseAction::RELEASE);
350     fingersId_.erase(event.id);
351     if (currentFingers_ < fingers_) {
352         if (isNeedResetVoluntarily_ && currentFingers_ == 1) {
353             ResetStateVoluntarily();
354             isNeedResetVoluntarily_ = false;
355         }
356         return;
357     }
358 
359     // In CrossPlatform, MOVE point has sampled, but the UP point is original coordinate,
360     // and participating in the Velocity calculation may cause abnormal rates
361     if (currentFingers_ == fingers_ && SystemProperties::IsNeedResampleTouchPoints()) {
362         UpdateTouchPointInVelocityTracker(event);
363     } else if (currentFingers_ > fingers_) {
364         panVelocity_.Reset(event.id);
365         UpdateTouchPointInVelocityTracker(event);
366     }
367 
368     UpdateTouchEventInfo(event);
369 
370     if ((currentFingers_ <= fingers_) &&
371         (refereeState_ != RefereeState::SUCCEED) && (refereeState_ != RefereeState::FAIL)) {
372         Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
373         return;
374     }
375 
376     if (refereeState_ == RefereeState::SUCCEED) {
377         if (currentFingers_ == fingers_) {
378             if (std::abs(panVelocity_.GetMainAxisVelocity()) <= MIN_SPEED_THRESHOLD) {
379                 DumpVelocityInfo(event.id);
380             }
381             // last one to fire end.
382             isStartTriggered_ = false;
383             SendCallbackMsg(onActionEnd_, GestureCallbackType::END);
384             averageDistance_.Reset();
385             AddOverTimeTrace();
386             lastRefereeState_ = RefereeState::READY;
387             refereeState_ = RefereeState::READY;
388             if (currentFingers_ > 1) {
389                 isNeedResetVoluntarily_ = true;
390             } else {
391                 ResetStateVoluntarily();
392             }
393         }
394     }
395 
396     // Clear All fingers' velocity when fingersId is empty.
397     if (fingersId_.empty()) {
398         panVelocity_.ResetAll();
399         isTouchEventFinished_ = true;
400     }
401 }
402 
HandleTouchUpEvent(const AxisEvent & event)403 void PanRecognizer::HandleTouchUpEvent(const AxisEvent& event)
404 {
405     isTouchEventFinished_ = false;
406     lastAction_ = static_cast<int32_t>(AxisAction::END);
407     // if axisEvent received rotateEvent, no need to active Pan recognizer.
408     if (event.isRotationEvent) {
409         return;
410     }
411 
412     if (event.sourceTool == SourceTool::MOUSE) {
413         delta_ = event.ConvertToOffset();
414         mainDelta_ = GetMainAxisDelta();
415         averageDistance_ += delta_;
416     }
417 
418     globalPoint_ = Point(event.x, event.y);
419 
420     touchPoints_[event.id] = TouchEvent();
421     UpdateTouchPointWithAxisEvent(event);
422     UpdateAxisPointInVelocityTracker(event, true);
423     time_ = event.time;
424 
425     DumpVelocityInfo(event.id);
426     TAG_LOGI(AceLogTag::ACE_INPUTKEYFLOW,
427         "PanVelocity main axis velocity is %{public}f", panVelocity_.GetMainAxisVelocity());
428 
429     if ((refereeState_ != RefereeState::SUCCEED) && (refereeState_ != RefereeState::FAIL)) {
430         Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
431         return;
432     }
433 
434     if (refereeState_ == RefereeState::SUCCEED) {
435         // AxisEvent is single one.
436         isStartTriggered_ = false;
437         SendCallbackMsg(onActionEnd_, GestureCallbackType::END);
438         AddOverTimeTrace();
439     }
440     panVelocity_.ResetAll();
441 }
442 
HandleTouchMoveEvent(const TouchEvent & event)443 void PanRecognizer::HandleTouchMoveEvent(const TouchEvent& event)
444 {
445     isTouchEventFinished_ = false;
446     lastAction_ = inputEventType_ == InputEventType::TOUCH_SCREEN ? static_cast<int32_t>(TouchType::MOVE)
447                                                                   : static_cast<int32_t>(MouseAction::MOVE);
448     if (static_cast<int32_t>(touchPoints_.size()) < fingers_) {
449         return;
450     }
451 
452     if (refereeState_ == RefereeState::FAIL) {
453         return;
454     }
455     UpdateTouchEventInfo(event);
456     UpdateTouchPointInVelocityTracker(event);
457     if (refereeState_ == RefereeState::DETECTING) {
458         auto result = IsPanGestureAccept();
459         if (result == GestureAcceptResult::ACCEPT) {
460             if (HandlePanAccept()) {
461                 return;
462             }
463         } else if (result == GestureAcceptResult::REJECT) {
464             Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
465         }
466     } else if (refereeState_ == RefereeState::SUCCEED) {
467         if ((direction_.type & PanDirection::VERTICAL) == 0) {
468             averageDistance_.SetY(0.0);
469             for (auto& element : touchPointsDistance_) {
470                 element.second.SetY(0.0);
471             }
472         } else if ((direction_.type & PanDirection::HORIZONTAL) == 0) {
473             averageDistance_.SetX(0.0);
474             for (auto& element : touchPointsDistance_) {
475                 element.second.SetX(0.0);
476             }
477         }
478         if (isFlushTouchEventsEnd_) {
479             if (!isStartTriggered_ && IsEnabled()) {
480                 SendCallbackMsg(onActionStart_, GestureCallbackType::START);
481                 isStartTriggered_ = true;
482             }
483             if (static_cast<int32_t>(touchPoints_.size()) > fingers_ && isLimitFingerCount_) {
484                 return;
485             }
486             SendCallbackMsg(onActionUpdate_, GestureCallbackType::UPDATE);
487         }
488     }
489 }
490 
OnFlushTouchEventsBegin()491 void PanRecognizer::OnFlushTouchEventsBegin()
492 {
493     isFlushTouchEventsEnd_ = false;
494 }
495 
OnFlushTouchEventsEnd()496 void PanRecognizer::OnFlushTouchEventsEnd()
497 {
498     isFlushTouchEventsEnd_ = true;
499 }
500 
UpdateAxisDeltaTransform(const AxisEvent & event)501 void PanRecognizer::UpdateAxisDeltaTransform(const AxisEvent& event)
502 {
503     if (event.sourceTool == SourceTool::MOUSE) {
504         if ((direction_.type & PanDirection::HORIZONTAL) == 0) { // Direction is vertical
505             delta_.SetX(0.0);
506         } else if ((direction_.type & PanDirection::VERTICAL) == 0) { // Direction is horizontal
507             delta_.SetY(0.0);
508         }
509     } else if (event.sourceTool == SourceTool::TOUCHPAD) {
510         PointF originPoint(lastAxisEvent_.horizontalAxis, lastAxisEvent_.verticalAxis);
511         PointF finalPoint(originPoint.GetX() + delta_.GetX(), originPoint.GetY() + delta_.GetY());
512         TransformForRecognizer(originPoint, GetAttachedNode(), false, false, -1);
513         TransformForRecognizer(finalPoint, GetAttachedNode(), false, false, -1);
514         delta_ = Offset(finalPoint.GetX(), finalPoint.GetY()) - Offset(originPoint.GetX(), originPoint.GetY());
515     }
516 }
517 
HandleTouchMoveEvent(const AxisEvent & event)518 void PanRecognizer::HandleTouchMoveEvent(const AxisEvent& event)
519 {
520     isTouchEventFinished_ = false;
521     lastAction_ = static_cast<int32_t>(AxisAction::UPDATE);
522     if (fingers_ != AXIS_PAN_FINGERS || event.isRotationEvent) {
523         return;
524     }
525 
526     auto pipeline = PipelineContext::GetCurrentContextSafelyWithCheck();
527     bool isShiftKeyPressed = false;
528     bool hasDifferentDirectionGesture = false;
529     if (pipeline) {
530         isShiftKeyPressed = event.HasKey(KeyCode::KEY_SHIFT_LEFT) || event.HasKey(KeyCode::KEY_SHIFT_RIGHT);
531         hasDifferentDirectionGesture = pipeline->HasDifferentDirectionGesture();
532     }
533     delta_ = event.ConvertToOffset(isShiftKeyPressed, hasDifferentDirectionGesture);
534     UpdateAxisDeltaTransform(event);
535     globalPoint_ = Point(event.x, event.y);
536     mainDelta_ = GetMainAxisDelta();
537     averageDistance_ += delta_;
538 
539     UpdateTouchPointWithAxisEvent(event);
540     UpdateAxisPointInVelocityTracker(event);
541     time_ = event.time;
542 
543     if (refereeState_ == RefereeState::DETECTING) {
544         auto result = IsPanGestureAccept();
545         if (result == GestureAcceptResult::ACCEPT) {
546             if (HandlePanAccept()) {
547                 return;
548             }
549         } else if (result == GestureAcceptResult::REJECT) {
550             Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
551         }
552     } else if (refereeState_ == RefereeState::SUCCEED) {
553         if ((direction_.type & PanDirection::VERTICAL) == 0) {
554             averageDistance_.SetY(0.0);
555         } else if ((direction_.type & PanDirection::HORIZONTAL) == 0) {
556             averageDistance_.SetX(0.0);
557         }
558         if (!isStartTriggered_ && IsEnabled()) {
559             SendCallbackMsg(onActionStart_, GestureCallbackType::START);
560             isStartTriggered_ = true;
561         }
562         SendCallbackMsg(onActionUpdate_, GestureCallbackType::UPDATE);
563     }
564 }
565 
HandlePanExtAccept()566 bool PanRecognizer::HandlePanExtAccept()
567 {
568     if (onActionExtUpdate_ && *onActionExtUpdate_) {
569         auto callbackFunction = *onActionExtUpdate_;
570         GestureEvent info = GetGestureEventInfo();
571         callbackFunction(info);
572     }
573     return true;
574 }
575 
HandlePanAccept()576 bool PanRecognizer::HandlePanAccept()
577 {
578     if (gestureInfo_ && gestureInfo_->GetType() == GestureTypeName::DRAG) {
579         auto dragEventActuator = GetDragEventActuator();
580         CHECK_NULL_RETURN(dragEventActuator, true);
581         if (dragEventActuator->IsDragUserReject()) {
582             Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
583             return true;
584         }
585     }
586     if (CheckLimitFinger()) {
587         extraInfo_ += " isLFC: " + std::to_string(isLimitFingerCount_);
588         return false;
589     }
590     if (TriggerGestureJudgeCallback() == GestureJudgeResult::REJECT) {
591         Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
592         if (gestureInfo_ && gestureInfo_->GetType() == GestureTypeName::DRAG) {
593             auto dragEventActuator = GetDragEventActuator();
594             CHECK_NULL_RETURN(dragEventActuator, true);
595             dragEventActuator->SetIsDragUserReject(true);
596         }
597         return true;
598     }
599     if (IsBridgeMode()) {
600         OnAccepted();
601         return false;
602     }
603     Adjudicate(AceType::Claim(this), GestureDisposal::ACCEPT);
604     return false;
605 }
606 
HandleTouchCancelEvent(const TouchEvent & event)607 void PanRecognizer::HandleTouchCancelEvent(const TouchEvent& event)
608 {
609     extraInfo_ += "cancel received.";
610     lastAction_ = inputEventType_ == InputEventType::TOUCH_SCREEN ? static_cast<int32_t>(TouchType::CANCEL)
611                                                                   : static_cast<int32_t>(MouseAction::CANCEL);
612     if ((refereeState_ != RefereeState::SUCCEED) && (refereeState_ != RefereeState::FAIL)) {
613         Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
614         return;
615     }
616 
617     if (refereeState_ == RefereeState::SUCCEED && currentFingers_ == fingers_) {
618         // AxisEvent is single one.
619         SendCallbackMsg(onActionCancel_, GestureCallbackType::CANCEL);
620         lastRefereeState_ = RefereeState::READY;
621         refereeState_ = RefereeState::READY;
622     } else if (refereeState_ == RefereeState::SUCCEED) {
623         TAG_LOGI(AceLogTag::ACE_INPUTKEYFLOW,
624             "PanRecognizer touchPoints size not equal fingers_, not send cancel callback.");
625     }
626 }
627 
HandleTouchCancelEvent(const AxisEvent & event)628 void PanRecognizer::HandleTouchCancelEvent(const AxisEvent& event)
629 {
630     extraInfo_ += "cancel received.";
631     isTouchEventFinished_ = false;
632     lastAction_ = static_cast<int32_t>(AxisAction::CANCEL);
633     if ((refereeState_ != RefereeState::SUCCEED) && (refereeState_ != RefereeState::FAIL)) {
634         Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
635         return;
636     }
637 
638     if (refereeState_ == RefereeState::SUCCEED) {
639         SendCallbackMsg(onActionCancel_, GestureCallbackType::CANCEL);
640     }
641 }
642 
JudgeVerticalDistance() const643 bool PanRecognizer::JudgeVerticalDistance() const
644 {
645     if (direction_.type == PanDirection::VERTICAL) {
646         return true;
647     }
648     for (const auto& element : touchPointsDistance_) {
649         auto each_point_move = element.second.GetY();
650         if ((((direction_.type & PanDirection::DOWN) == 0) && GreatOrEqual(each_point_move, 0.0)) ||
651             ((((direction_.type & PanDirection::UP) == 0) && LessOrEqual(each_point_move, 0.0)))) {
652             continue;
653         }
654         return true;
655     }
656     return false;
657 }
658 
CalculateTruthFingers(bool isDirectionUp) const659 bool PanRecognizer::CalculateTruthFingers(bool isDirectionUp) const
660 {
661     float totalDistance = 0.0f;
662     for (auto& element : touchPointsDistance_) {
663         auto each_point_move = element.second.GetY();
664         if (GreatNotEqual(each_point_move, 0.0) && isDirectionUp) {
665             totalDistance += each_point_move;
666         } else if (LessNotEqual(each_point_move, 0.0) && !isDirectionUp) {
667             totalDistance -= each_point_move;
668         }
669     }
670     auto judgeDistance = GetDistanceConfigFor(deviceTool_);
671     return GreatOrEqual(totalDistance, judgeDistance) && static_cast<int32_t>(touchPointsDistance_.size()) >= fingers_;
672 }
673 
IsPanGestureAcceptInAllDirection(double judgeDistance) const674 PanRecognizer::GestureAcceptResult PanRecognizer::IsPanGestureAcceptInAllDirection(double judgeDistance) const
675 {
676     double offset = averageDistance_.GetDistance();
677     if (fabs(offset) < judgeDistance) {
678         return GestureAcceptResult::DETECTING;
679     }
680     return GestureAcceptResult::ACCEPT;
681 }
682 
IsPanGestureAcceptInHorizontalDirection(double judgeDistance) const683 PanRecognizer::GestureAcceptResult PanRecognizer::IsPanGestureAcceptInHorizontalDirection(double judgeDistance) const
684 {
685     if ((direction_.type & PanDirection::HORIZONTAL) != 0) {
686         double offset = averageDistance_.GetX();
687         if (fabs(offset) < judgeDistance) {
688             return GestureAcceptResult::DETECTING;
689         }
690         if ((direction_.type & PanDirection::LEFT) == 0 && offset < 0) {
691             return GestureAcceptResult::REJECT;
692         }
693         if ((direction_.type & PanDirection::RIGHT) == 0 && offset > 0) {
694             return GestureAcceptResult::REJECT;
695         }
696         return GestureAcceptResult::ACCEPT;
697     }
698     return GestureAcceptResult::DETECTING;
699 }
700 
IsPanGestureAcceptInVerticalDirection(double judgeDistance) const701 PanRecognizer::GestureAcceptResult PanRecognizer::IsPanGestureAcceptInVerticalDirection(double judgeDistance) const
702 {
703     if ((direction_.type & PanDirection::VERTICAL) != 0) {
704         double offset = averageDistance_.GetY();
705         if (fabs(offset) < judgeDistance) {
706             return GestureAcceptResult::DETECTING;
707         }
708         if (inputEventType_ == InputEventType::AXIS) {
709             if ((direction_.type & PanDirection::UP) == 0 && offset < 0) {
710                 return GestureAcceptResult::REJECT;
711             }
712             if ((direction_.type & PanDirection::DOWN) == 0 && offset > 0) {
713                 return GestureAcceptResult::REJECT;
714             }
715         } else {
716             if (!JudgeVerticalDistance()) {
717                 return GestureAcceptResult::REJECT;
718             }
719             if ((direction_.type & PanDirection::UP) == 0) {
720                 return CalculateTruthFingers(true) ? GestureAcceptResult::ACCEPT : GestureAcceptResult::REJECT;
721             }
722             if ((direction_.type & PanDirection::DOWN) == 0) {
723                 return CalculateTruthFingers(false) ? GestureAcceptResult::ACCEPT : GestureAcceptResult::REJECT;
724             }
725         }
726         return GestureAcceptResult::ACCEPT;
727     }
728     return GestureAcceptResult::DETECTING;
729 }
730 
IsPanGestureAccept() const731 PanRecognizer::GestureAcceptResult PanRecognizer::IsPanGestureAccept() const
732 {
733     auto judgeDistance = GetDistanceConfigFor(deviceTool_);
734     if (NearZero(judgeDistance) && direction_.type != PanDirection::NONE) {
735         return GestureAcceptResult::ACCEPT;
736     }
737     if ((direction_.type & PanDirection::ALL) == PanDirection::ALL) {
738         return IsPanGestureAcceptInAllDirection(judgeDistance);
739     }
740 
741     if (fabs(averageDistance_.GetX()) > fabs(averageDistance_.GetY())) {
742         return IsPanGestureAcceptInHorizontalDirection(judgeDistance);
743     }
744     return IsPanGestureAcceptInVerticalDirection(judgeDistance);
745 }
746 
GetRawGlobalLocation(int32_t postEventNodeId)747 Offset PanRecognizer::GetRawGlobalLocation(int32_t postEventNodeId)
748 {
749     PointF localPoint(globalPoint_.GetX(), globalPoint_.GetY());
750     if (!lastTouchEvent_.history.empty() && (gestureInfo_ && gestureInfo_->GetType() == GestureTypeName::BOXSELECT)) {
751         auto lastPoint = lastTouchEvent_.history.back();
752         PointF rawLastPoint(lastPoint.GetOffset().GetX(), lastPoint.GetOffset().GetY());
753         TransformForRecognizer(
754             rawLastPoint, GetAttachedNode(), false, isPostEventResult_, postEventNodeId);
755         return Offset(rawLastPoint.GetX(), rawLastPoint.GetY());
756     }
757     TransformForRecognizer(
758         localPoint, GetAttachedNode(), false, isPostEventResult_, postEventNodeId);
759     return Offset(localPoint.GetX(), localPoint.GetY());
760 }
761 
OnResetStatus()762 void PanRecognizer::OnResetStatus()
763 {
764     MultiFingersRecognizer::OnResetStatus();
765     touchPoints_.clear();
766     averageDistance_.Reset();
767     touchPointsDistance_.clear();
768     panVelocity_.ResetAll();
769     isStartTriggered_ = false;
770     localMatrix_.clear();
771     delta_ = Offset();
772     globalPoint_ = Point();
773     mainDelta_ = 0.0;
774     isFlushTouchEventsEnd_ = false;
775     isForDrag_ = false;
776     isStartTriggered_ = false;
777 }
778 
OnSucceedCancel()779 void PanRecognizer::OnSucceedCancel()
780 {
781     SendCallbackMsg(onActionCancel_, GestureCallbackType::CANCEL);
782 }
783 
GetGestureEventHalfInfo(GestureEvent * info)784 void PanRecognizer::GetGestureEventHalfInfo(GestureEvent* info)
785 {
786     info->SetDeviceId(deviceId_);
787     info->SetFingerList(fingerList_);
788     info->SetSourceDevice(deviceType_);
789     info->SetOffsetX((direction_.type & PanDirection::HORIZONTAL) == 0 ? 0.0 : averageDistance_.GetX());
790     info->SetOffsetY((direction_.type & PanDirection::VERTICAL) == 0 ? 0.0 : averageDistance_.GetY());
791     info->SetDelta(delta_);
792     info->SetVelocity(panVelocity_.GetVelocity());
793     info->SetGestureTypeName(GestureTypeName::PAN_GESTURE);
794     info->SetMainVelocity(panVelocity_.GetMainAxisVelocity());
795 }
796 
GetGestureEventInfo()797 GestureEvent PanRecognizer::GetGestureEventInfo()
798 {
799     GestureEvent info;
800     info.SetTimeStamp(time_);
801     UpdateFingerListInfo();
802     GetGestureEventHalfInfo(&info);
803     TouchEvent touchPoint = {};
804     if (!touchPoints_.empty()) {
805         touchPoint = touchPoints_.begin()->second;
806     }
807     PointF localPoint(globalPoint_.GetX(), globalPoint_.GetY());
808     TransformForRecognizer(
809         localPoint, GetAttachedNode(), false, isPostEventResult_, touchPoint.postEventNodeId);
810     info.SetRawGlobalLocation(GetRawGlobalLocation(touchPoint.postEventNodeId));
811     info.SetPointerId(inputEventType_ == InputEventType::AXIS ? lastAxisEvent_.id : lastTouchEvent_.id);
812     info.SetTargetDisplayId(touchPoint.targetDisplayId);
813     info.SetIsInterpolated(touchPoint.isInterpolated);
814     info.SetInputXDeltaSlope(touchPoint.inputXDeltaSlope);
815     info.SetInputYDeltaSlope(touchPoint.inputYDeltaSlope);
816     info.SetMainDelta(mainDelta_ / static_cast<double>(touchPoints_.size()));
817     if (inputEventType_ == InputEventType::AXIS) {
818         info.SetScreenLocation(lastAxisEvent_.GetScreenOffset());
819         info.SetGlobalDisplayLocation(lastAxisEvent_.GetGlobalDisplayOffset());
820         info.SetSourceTool(lastAxisEvent_.sourceTool);
821         info.SetVerticalAxis(lastAxisEvent_.verticalAxis);
822         info.SetHorizontalAxis(lastAxisEvent_.horizontalAxis);
823         info.SetPressedKeyCodes(lastAxisEvent_.pressedCodes);
824         info.SetPointerEventId(lastAxisEvent_.touchEventId);
825         info.CopyConvertInfoFrom(lastAxisEvent_.convertInfo);
826         info.SetPassThrough(lastAxisEvent_.passThrough);
827     } else {
828         info.SetScreenLocation(lastTouchEvent_.GetScreenOffset());
829         info.SetGlobalDisplayLocation(lastTouchEvent_.GetGlobalDisplayOffset());
830         info.SetSourceTool(lastTouchEvent_.sourceTool);
831         info.SetPressedKeyCodes(lastTouchEvent_.pressedKeyCodes_);
832         info.SetPointerEventId(lastTouchEvent_.touchEventId);
833         info.CopyConvertInfoFrom(lastTouchEvent_.convertInfo);
834         info.SetPassThrough(lastTouchEvent_.passThrough);
835     }
836     info.SetGlobalPoint(globalPoint_).SetLocalLocation(Offset(localPoint.GetX(), localPoint.GetY()));
837     info.SetTarget(GetEventTarget().value_or(EventTarget()));
838     info.SetInputEventType(inputEventType_);
839     info.SetForce(lastTouchEvent_.force);
840     info.SetTiltX(lastTouchEvent_.tiltX.value_or(0.0));
841     info.SetTiltY(lastTouchEvent_.tiltY.value_or(0.0));
842     info.SetRollAngle(lastTouchEvent_.rollAngle.value_or(0.0));
843     info.SetPointerEvent(lastPointEvent_);
844     info.SetIsPostEventResult(isPostEventResult_);
845     info.SetPostEventNodeId(lastTouchEvent_.postEventNodeId);
846     info.SetLastAction(lastAction_);
847     return info;
848 }
849 
SendCallbackMsg(const std::unique_ptr<GestureEventFunc> & callback,GestureCallbackType type)850 void PanRecognizer::SendCallbackMsg(const std::unique_ptr<GestureEventFunc>& callback, GestureCallbackType type)
851 {
852     std::string callbackName = GetCallbackName(callback);
853     if (type == GestureCallbackType::START || type == GestureCallbackType::END || type == GestureCallbackType::CANCEL) {
854         std::string callbackTypeStr = (type == GestureCallbackType::START) ? "START" :
855             (type == GestureCallbackType::END) ? "END" : "CANCEL";
856         extraInfo_ += " " + callbackTypeStr
857             + " cBk: " + std::to_string((callback && *callback))
858             + " isE: "  + std::to_string(IsEnabled())
859             + " gIn: " + std::to_string((!gestureInfo_ || !gestureInfo_->GetDisposeTag()));
860     }
861     ACE_SCOPED_TRACE("PanRecognizer %s, mainDelta: %f", callbackName.c_str(), mainDelta_);
862     if ((type == GestureCallbackType::END || type == GestureCallbackType::CANCEL) && !IsEnabled()) {
863         if (panEndOnDisableState_ && *panEndOnDisableState_ && (!gestureInfo_ || !gestureInfo_->GetDisposeTag())) {
864             GestureEvent info = GetGestureEventInfo();
865             // callback may be overwritten in its invoke so we copy it first
866             auto callbackFunction = *panEndOnDisableState_;
867             callbackFunction(info);
868             HandleReports(info, type);
869             return;
870         }
871     }
872     if (callback && *callback && IsEnabled() && (!gestureInfo_ || !gestureInfo_->GetDisposeTag())) {
873         GestureEvent info = GetGestureEventInfo();
874         // callback may be overwritten in its invoke so we copy it first
875         auto callbackFunction = *callback;
876         HandleCallbackReports(info, type, PanGestureState::BEFORE);
877         callbackFunction(info);
878         HandleCallbackReports(info, type, PanGestureState::AFTER);
879     }
880 }
881 
HandleCallbackReports(const GestureEvent & info,GestureCallbackType type,PanGestureState panGestureState)882 void PanRecognizer::HandleCallbackReports(
883     const GestureEvent& info, GestureCallbackType type, PanGestureState panGestureState)
884 {
885     if (panGestureState == PanGestureState::BEFORE) {
886         HandleGestureAccept(info, type, GestureListenerType::PAN);
887     } else if (panGestureState == PanGestureState::AFTER) {
888         HandleReports(info, type);
889     }
890     HandlePanGestureAccept(info, panGestureState, type);
891 }
892 
HandleReports(const GestureEvent & info,GestureCallbackType type)893 void PanRecognizer::HandleReports(const GestureEvent& info, GestureCallbackType type)
894 {
895     if (type == GestureCallbackType::ACTION || type == GestureCallbackType::UPDATE) {
896         return;
897     }
898     auto frameNode = GetAttachedNode().Upgrade();
899     CHECK_NULL_VOID(frameNode);
900     PanJsonReport panReport;
901     panReport.SetCallbackType(type);
902     panReport.SetGestureType(GetRecognizerType());
903     panReport.SetId(frameNode->GetId());
904     panReport.SetPanDirection(static_cast<int32_t>(direction_.type));
905     panReport.SetPoint(info.GetGlobalPoint());
906     Reporter::GetInstance().HandleUISessionReporting(panReport);
907 }
908 
TriggerGestureJudgeCallback()909 GestureJudgeResult PanRecognizer::TriggerGestureJudgeCallback()
910 {
911     auto targetComponent = GetTargetComponent();
912     CHECK_NULL_RETURN(targetComponent, GestureJudgeResult::CONTINUE);
913     auto gestureRecognizerJudgeFunc = targetComponent->GetOnGestureRecognizerJudgeBegin();
914     auto callback = targetComponent->GetOnGestureJudgeBeginCallback();
915     auto callbackNative = targetComponent->GetOnGestureJudgeNativeBeginCallback();
916     if (!callback && !callbackNative && !sysJudge_ && !gestureRecognizerJudgeFunc) {
917         return GestureJudgeResult::CONTINUE;
918     }
919     auto info = std::make_shared<PanGestureEvent>();
920     UpdateFingerListInfo();
921     UpdateGestureEventInfo(info);
922     if (gestureInfo_) {
923         gestureInfo_->SetInputEventType(inputEventType_);
924     }
925     if (gestureRecognizerJudgeFunc &&
926         gestureRecognizerJudgeFunc(info, Claim(this), responseLinkRecognizer_) == GestureJudgeResult::REJECT) {
927         return GestureJudgeResult::REJECT;
928     }
929     if (!gestureRecognizerJudgeFunc && callback && callback(gestureInfo_, info) == GestureJudgeResult::REJECT) {
930         // If outer callback exits, prioritize checking outer callback. If outer reject, return reject.
931         return GestureJudgeResult::REJECT;
932     }
933     if (callbackNative && callbackNative(gestureInfo_, info) == GestureJudgeResult::REJECT) {
934         // If outer callback doesn't exit or accept, check inner callback. If inner reject, return reject.
935         return GestureJudgeResult::REJECT;
936     }
937     if (sysJudge_ && sysJudge_(gestureInfo_, info) == GestureJudgeResult::REJECT) {
938         return GestureJudgeResult::REJECT;
939     }
940     return GestureJudgeResult::CONTINUE;
941 }
942 
UpdateGestureEventInfo(std::shared_ptr<PanGestureEvent> & info)943 void PanRecognizer::UpdateGestureEventInfo(std::shared_ptr<PanGestureEvent>& info)
944 {
945     info->SetFingerList(fingerList_);
946     info->SetTimeStamp(time_);
947     info->SetDeviceId(deviceId_);
948     info->SetOffsetX((direction_.type & PanDirection::HORIZONTAL) == 0 ? 0.0 : averageDistance_.GetX());
949     info->SetOffsetY((direction_.type & PanDirection::VERTICAL) == 0 ? 0.0 : averageDistance_.GetY());
950     info->SetSourceDevice(deviceType_);
951     if (inputEventType_ == InputEventType::AXIS) {
952         info->SetVelocity(Velocity());
953         info->SetMainVelocity(0.0);
954         info->SetSourceTool(lastAxisEvent_.sourceTool);
955         info->SetVerticalAxis(lastAxisEvent_.verticalAxis);
956         info->SetHorizontalAxis(lastAxisEvent_.horizontalAxis);
957         info->SetPressedKeyCodes(lastAxisEvent_.pressedCodes);
958         info->SetTargetDisplayId(lastAxisEvent_.targetDisplayId);
959     } else {
960         info->SetVelocity(panVelocity_.GetVelocity());
961         info->SetMainVelocity(panVelocity_.GetMainAxisVelocity());
962         info->SetSourceTool(lastTouchEvent_.sourceTool);
963         info->SetPressedKeyCodes(lastTouchEvent_.pressedKeyCodes_);
964         info->SetTargetDisplayId(lastTouchEvent_.targetDisplayId);
965     }
966     info->SetTarget(GetEventTarget().value_or(EventTarget()));
967     info->SetForce(lastTouchEvent_.force);
968     info->SetRawInputEventType(inputEventType_);
969     info->SetRawInputEvent(lastPointEvent_);
970     info->SetRawInputDeviceId(deviceId_);
971     info->SetLastAction(lastAction_);
972     if (lastTouchEvent_.tiltX.has_value()) {
973         info->SetTiltX(lastTouchEvent_.tiltX.value());
974     }
975     if (lastTouchEvent_.tiltY.has_value()) {
976         info->SetTiltY(lastTouchEvent_.tiltY.value());
977     }
978     if (lastTouchEvent_.rollAngle.has_value()) {
979         info->SetRollAngle(lastTouchEvent_.rollAngle.value());
980     }
981 }
982 
ReconcileFrom(const RefPtr<NGGestureRecognizer> & recognizer)983 bool PanRecognizer::ReconcileFrom(const RefPtr<NGGestureRecognizer>& recognizer)
984 {
985     RefPtr<PanRecognizer> curr = AceType::DynamicCast<PanRecognizer>(recognizer);
986     if (!curr) {
987         ResetStatus();
988         return false;
989     }
990 
991     if (curr->fingers_ != fingers_ || curr->priorityMask_ != priorityMask_) {
992         if (refereeState_ == RefereeState::SUCCEED && static_cast<int32_t>(touchPoints_.size()) >= fingers_) {
993             SendCallbackMsg(onActionCancel_, GestureCallbackType::CANCEL);
994         }
995         ResetStatus();
996         return false;
997     }
998 
999     direction_.type = curr->direction_.type;
1000     newDirection_.type = curr->newDirection_.type;
1001     distance_ = curr->distance_;
1002     newDistance_ = curr->newDistance_;
1003     mouseDistance_ = curr->mouseDistance_;
1004     distanceMap_ = curr->distanceMap_;
1005     newDistanceMap_ = curr->newDistanceMap_;
1006     isLimitFingerCount_ = curr->isLimitFingerCount_;
1007 
1008     onActionStart_ = std::move(curr->onActionStart_);
1009     onActionUpdate_ = std::move(curr->onActionUpdate_);
1010     onActionExtUpdate_ = std::move(curr->onActionExtUpdate_);
1011     onActionEnd_ = std::move(curr->onActionEnd_);
1012     onActionCancel_ = std::move(curr->onActionCancel_);
1013     ReconcileGestureInfoFrom(recognizer);
1014     return true;
1015 }
1016 
GetAxisDirection()1017 Axis PanRecognizer::GetAxisDirection()
1018 {
1019     auto hasHorizontal = direction_.type & PanDirection::HORIZONTAL;
1020     auto hasVertical = direction_.type & PanDirection::VERTICAL;
1021     if (direction_.type == PanDirection::ALL || (hasHorizontal && hasVertical)) {
1022         return Axis::FREE;
1023     }
1024     if (hasHorizontal) {
1025         return Axis::HORIZONTAL;
1026     }
1027     if (hasVertical) {
1028         return Axis::VERTICAL;
1029     }
1030     return Axis::NONE;
1031 }
1032 
SetDirection(const PanDirection & direction)1033 void PanRecognizer::SetDirection(const PanDirection& direction)
1034 {
1035     ChangeDirection(direction);
1036     panVelocity_.SetDirection(direction_.type);
1037 }
1038 
ChangeFingers(int32_t fingers)1039 void PanRecognizer::ChangeFingers(int32_t fingers)
1040 {
1041     if (fingers_ != fingers) {
1042         newFingers_ = fingers;
1043     }
1044 }
1045 
ChangeDirection(const PanDirection & direction)1046 void PanRecognizer::ChangeDirection(const PanDirection& direction)
1047 {
1048     if (direction_.type != direction.type) {
1049         auto node = GetAttachedNode().Upgrade();
1050         TAG_LOGD(AceLogTag::ACE_GESTURE, "Pan change direction from %{public}d to %{public}d, tag = %{public}s",
1051             static_cast<int32_t>(direction_.type), static_cast<int32_t>(direction.type),
1052             node ? node->GetTag().c_str() : "null");
1053         direction_.type = direction.type;
1054         newDirection_.type = direction.type;
1055     }
1056 }
1057 
ChangeDistance(double distance)1058 void PanRecognizer::ChangeDistance(double distance)
1059 {
1060     if (GetDistanceConfigFor(SourceTool::UNKNOWN) != distance) {
1061         distanceMap_.clear();
1062         newDistanceMap_.clear();
1063         if (refereeState_ == RefereeState::READY || refereeState_ == RefereeState::DETECTING) {
1064             distanceMap_[SourceTool::UNKNOWN] = Dimension(
1065                 Dimension(distance, DimensionUnit::PX).ConvertToVp(), DimensionUnit::VP);
1066             distance_ = distance;
1067         }
1068         newDistanceMap_[SourceTool::UNKNOWN] = Dimension(
1069             Dimension(distance, DimensionUnit::PX).ConvertToVp(), DimensionUnit::VP);
1070         newDistance_ = distance;
1071         mouseDistance_ = distance;
1072     }
1073 }
1074 
SetMouseDistance(double distance)1075 void PanRecognizer::SetMouseDistance(double distance)
1076 {
1077     Dimension distanceDimension = Dimension(
1078         Dimension(distance, DimensionUnit::PX).ConvertToVp(), DimensionUnit::VP);
1079     distanceMap_[SourceTool::MOUSE] = distanceDimension;
1080     distanceMap_[SourceTool::TOUCHPAD] = distanceDimension;
1081     newDistanceMap_[SourceTool::MOUSE] = distanceDimension;
1082     newDistanceMap_[SourceTool::TOUCHPAD] = distanceDimension;
1083     mouseDistance_ = distance;
1084 }
1085 
GetDistance() const1086 double PanRecognizer::GetDistance() const
1087 {
1088     return GetDistanceConfigFor(deviceTool_);
1089 }
1090 
GetDistanceConfigFor(SourceTool sourceTool) const1091 double PanRecognizer::GetDistanceConfigFor(SourceTool sourceTool) const
1092 {
1093     if (distanceMap_.find(sourceTool) != distanceMap_.end()) {
1094         return distanceMap_.at(sourceTool).ConvertToPx();
1095     }
1096     if (distanceMap_.find(SourceTool::UNKNOWN) != distanceMap_.end()) {
1097         return distanceMap_.at(SourceTool::UNKNOWN).ConvertToPx();
1098     }
1099     return distance_;
1100 }
1101 
SetDistanceMap(const PanDistanceMap & distanceMap)1102 void PanRecognizer::SetDistanceMap(const PanDistanceMap& distanceMap)
1103 {
1104     distanceMap_.clear();
1105     newDistanceMap_.clear();
1106     for (auto& iter : distanceMap) {
1107         auto distanceDimension = Dimension(
1108             Dimension(iter.second, DimensionUnit::PX).ConvertToVp(), DimensionUnit::VP);
1109         distanceMap_[iter.first] = distanceDimension;
1110         newDistanceMap_[iter.first] = distanceDimension;
1111     }
1112 }
1113 
GetMainAxisDelta()1114 double PanRecognizer::GetMainAxisDelta()
1115 {
1116     switch (direction_.type) {
1117         case PanDirection::ALL:
1118             return delta_.GetDistance();
1119         case PanDirection::HORIZONTAL:
1120             return delta_.GetX();
1121         case PanDirection::VERTICAL:
1122             return delta_.GetY();
1123         default:
1124             return 0.0;
1125     }
1126 }
1127 
Dump() const1128 RefPtr<GestureSnapshot> PanRecognizer::Dump() const
1129 {
1130     RefPtr<GestureSnapshot> info = NGGestureRecognizer::Dump();
1131     std::stringstream oss;
1132     oss << "direction: " << direction_.type << ", "
1133         << "isForDrag: " << isForDrag_ << ", "
1134         << "distanceMap: [";
1135     for (auto iter : distanceMap_) {
1136         oss << "sourceTool: " << std::to_string(static_cast<int32_t>(iter.first)) << ", "
1137             << "distance: " << iter.second.ConvertToPx() << ", ";
1138     }
1139     oss << "], distance: " << GetDistanceConfigFor(deviceTool_) << ", "
1140         << "fingers: " << fingers_ << ", "
1141         << DumpGestureInfo();
1142     info->customInfo = oss.str();
1143     return info;
1144 }
1145 
GetDragEventActuator()1146 RefPtr<DragEventActuator> PanRecognizer::GetDragEventActuator()
1147 {
1148     auto targetComponent = GetTargetComponent();
1149     CHECK_NULL_RETURN(targetComponent, nullptr);
1150     auto uiNode = targetComponent->GetUINode().Upgrade();
1151     CHECK_NULL_RETURN(uiNode, nullptr);
1152     auto frameNode = AceType::DynamicCast<FrameNode>(uiNode);
1153     CHECK_NULL_RETURN(frameNode, nullptr);
1154     auto gestureEventHub = frameNode->GetOrCreateGestureEventHub();
1155     CHECK_NULL_RETURN(gestureEventHub, nullptr);
1156     return gestureEventHub->GetDragEventActuator();
1157 }
1158 
GetFastestTracker(std::function<double (VelocityTracker &)> && func)1159 int32_t PanRecognizer::PanVelocity::GetFastestTracker(std::function<double(VelocityTracker&)>&& func)
1160 {
1161     int32_t maxId = -1;
1162     double maxV = 0.0;
1163     for (auto& [id, tracker] : trackerMap_) {
1164         double v = std::abs(func(tracker));
1165         if (v > maxV) {
1166             maxId = id;
1167             maxV = v;
1168         }
1169     }
1170     return maxId;
1171 }
1172 
GetVelocity()1173 Velocity PanRecognizer::PanVelocity::GetVelocity()
1174 {
1175     auto&& func = [](VelocityTracker& tracker) { return tracker.GetVelocity().GetVelocityValue(); };
1176     int32_t id = GetFastestTracker(func);
1177     return (id != -1) ? trackerMap_[id].GetVelocity() : Velocity();
1178 }
1179 
GetMainAxisVelocity()1180 double PanRecognizer::PanVelocity::GetMainAxisVelocity()
1181 {
1182     auto&& func = [axis = axis_](VelocityTracker& tracker) {
1183         tracker.SetMainAxis(axis);
1184         return tracker.GetMainAxisVelocity();
1185     };
1186     int32_t id = GetFastestTracker(func);
1187     return (id != -1) ? trackerMap_[id].GetMainAxisVelocity() : 0.0;
1188 }
1189 
UpdateTouchPoint(int32_t id,const TouchEvent & event,bool end)1190 void PanRecognizer::PanVelocity::UpdateTouchPoint(int32_t id, const TouchEvent& event, bool end)
1191 {
1192     trackerMap_[id].UpdateTouchPoint(event, end,
1193         event.sourceTool == SourceTool::TOUCHPAD ? TOUCHPAD_STILL_THRESHOLD : VelocityTracker::TOUCH_STILL_THRESHOLD);
1194 }
1195 
Reset(int32_t id)1196 void PanRecognizer::PanVelocity::Reset(int32_t id)
1197 {
1198     trackerMap_.erase(id);
1199 }
1200 
ResetAll()1201 void PanRecognizer::PanVelocity::ResetAll()
1202 {
1203     trackerMap_.clear();
1204 }
1205 
SetDirection(int32_t directionType)1206 void PanRecognizer::PanVelocity::SetDirection(int32_t directionType)
1207 {
1208     auto axis = Axis::FREE;
1209     if ((directionType & PanDirection::VERTICAL) == 0) {
1210         axis = Axis::HORIZONTAL;
1211     } else if ((directionType & PanDirection::HORIZONTAL) == 0) {
1212         axis = Axis::VERTICAL;
1213     }
1214     axis_ = axis;
1215 }
1216 
AddOverTimeTrace()1217 void PanRecognizer::AddOverTimeTrace()
1218 {
1219     int64_t overTime = GetSysTimestamp();
1220     int64_t inputTime = overTime;
1221     if (firstInputTime_.has_value()) {
1222         inputTime = static_cast<int64_t>(firstInputTime_.value().time_since_epoch().count());
1223     }
1224     if (SystemProperties::GetTraceInputEventEnabled()) {
1225         ACE_SCOPED_TRACE("UserEvent InputTime:%lld OverTime:%lld InputType:PanGesture",
1226             static_cast<long long>(inputTime), static_cast<long long>(overTime));
1227     }
1228     firstInputTime_.reset();
1229 }
1230 
UpdateTouchEventInfo(const TouchEvent & event)1231 void PanRecognizer::UpdateTouchEventInfo(const TouchEvent& event)
1232 {
1233     globalPoint_ = Point(event.x, event.y);
1234     lastTouchEvent_ = event;
1235     PointF windowPoint(event.GetOffset().GetX(), event.GetOffset().GetY());
1236     PointF windowTouchPoint(touchPoints_[event.id].GetOffset().GetX(), touchPoints_[event.id].GetOffset().GetY());
1237     TransformForRecognizer(windowPoint, GetAttachedNode(), false, isPostEventResult_, event.postEventNodeId);
1238     TransformForRecognizer(
1239         windowTouchPoint, GetAttachedNode(), false, isPostEventResult_, event.postEventNodeId);
1240     delta_ =
1241         (Offset(windowPoint.GetX(), windowPoint.GetY()) - Offset(windowTouchPoint.GetX(), windowTouchPoint.GetY()));
1242 
1243     if (SystemProperties::GetDebugEnabled()) {
1244         TAG_LOGD(AceLogTag::ACE_GESTURE, "Delta is x %{public}f, y %{public}f ", delta_.GetX(), delta_.GetY());
1245     }
1246     mainDelta_ = GetMainAxisDelta();
1247     averageDistance_ += delta_ / static_cast<double>(touchPoints_.size());
1248     touchPoints_[event.id] = event;
1249     touchPointsDistance_[event.id] += delta_;
1250     time_ = event.time;
1251 }
1252 
DispatchPanStartedToPerf(const TouchEvent & event)1253 void PanRecognizer::DispatchPanStartedToPerf(const TouchEvent& event)
1254 {
1255     int64_t inputTime = event.time.time_since_epoch().count();
1256     if (inputTime <= 0 || event.sourceType != SourceType::TOUCH) {
1257         return;
1258     }
1259     PerfMonitor* pMonitor = PerfMonitor::GetPerfMonitor();
1260     if (pMonitor == nullptr) {
1261         return;
1262     }
1263     pMonitor->RecordInputEvent(FIRST_MOVE, PERF_TOUCH_EVENT, inputTime);
1264 }
1265 
DumpVelocityInfo(int32_t fingerId)1266 void PanRecognizer::DumpVelocityInfo(int32_t fingerId)
1267 {
1268     auto velocityTrackerIter = panVelocity_.GetVelocityMap().find(fingerId);
1269     if (velocityTrackerIter != panVelocity_.GetVelocityMap().end()) {
1270         velocityTrackerIter->second.DumpVelocityPoints();
1271     } else {
1272         TAG_LOGI(AceLogTag::ACE_GESTURE, "Dump velocity fail with fingerId:%{public}d", fingerId);
1273     }
1274 }
1275 
HandlePanGestureAccept(const GestureEvent & info,PanGestureState panGestureState,GestureCallbackType type)1276 void PanRecognizer::HandlePanGestureAccept(
1277     const GestureEvent& info, PanGestureState panGestureState, GestureCallbackType type)
1278 {
1279     if (type == GestureCallbackType::START) {
1280         currentCallbackState_ = CurrentCallbackState::START;
1281         auto node = GetAttachedNode().Upgrade();
1282         UIObserverHandler::GetInstance().NotifyPanGestureStateChange(
1283             info, Claim(this), node, { panGestureState, currentCallbackState_ });
1284     } else if (type == GestureCallbackType::END) {
1285         currentCallbackState_ = CurrentCallbackState::END;
1286         auto node = GetAttachedNode().Upgrade();
1287         UIObserverHandler::GetInstance().NotifyPanGestureStateChange(
1288             info, Claim(this), node, { panGestureState, currentCallbackState_ });
1289     }
1290 }
1291 } // namespace OHOS::Ace::NG
1292