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