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/gestures/recognizers/multi_fingers_recognizer.h"
17 
18 #include "base/memory/ace_type.h"
19 #include "core/components_ng/gestures/recognizers/recognizer_group.h"
20 
21 namespace OHOS::Ace::NG {
22 namespace {
23 constexpr int32_t DEFAULT_MAX_FINGERS = 10;
24 } // namespace
25 
MultiFingersRecognizer(int32_t fingers)26 MultiFingersRecognizer::MultiFingersRecognizer(int32_t fingers)
27 {
28     if (fingers > DEFAULT_MAX_FINGERS || fingers <= 0) {
29         fingers_ = 1;
30     } else {
31         fingers_ = fingers;
32     }
33 }
34 
UpdateFingerListInfo()35 void MultiFingersRecognizer::UpdateFingerListInfo()
36 {
37     fingerList_.clear();
38     lastPointEvent_.reset();
39     auto maxTimeStamp = TimeStamp::min().time_since_epoch().count();
40     for (const auto& point : touchPoints_) {
41         PointF localPoint(point.second.x, point.second.y);
42         NGGestureRecognizer::Transform(localPoint, GetAttachedNode(), false,
43             isPostEventResult_, point.second.postEventNodeId);
44         FingerInfo fingerInfo = { point.second.originalId, point.second.GetOffset(),
45             Offset(localPoint.GetX(), localPoint.GetY()),
46             point.second.GetScreenOffset(), point.second.sourceType, point.second.sourceTool };
47         fingerList_.emplace_back(fingerInfo);
48         if (maxTimeStamp <= point.second.GetTimeStamp().time_since_epoch().count()
49             && point.second.pointers.size() >= touchPoints_.size()) {
50             lastPointEvent_ = point.second.pointerEvent;
51             maxTimeStamp = point.second.GetTimeStamp().time_since_epoch().count();
52         }
53     }
54 }
55 
IsNeedResetStatus()56 bool MultiFingersRecognizer::IsNeedResetStatus()
57 {
58     if (GetValidFingersCount() != 0) {
59         return false;
60     }
61 
62     auto ref = AceType::Claim(this);
63     auto group = AceType::DynamicCast<RecognizerGroup>(ref);
64     if (!group) {
65         return true;
66     }
67 
68     auto groupList = group->GetGroupRecognizer();
69     for (auto &recognizer : groupList) {
70         auto multiFingersRecognizer = AceType::DynamicCast<MultiFingersRecognizer>(recognizer);
71         if (!multiFingersRecognizer) {
72             continue;
73         }
74 
75         if (!multiFingersRecognizer->IsNeedResetStatus()) {
76             return false;
77         }
78     }
79 
80     return true;
81 }
82 
OnFinishGestureReferee(int32_t touchId,bool isBlocked)83 void MultiFingersRecognizer::OnFinishGestureReferee(int32_t touchId, bool isBlocked)
84 {
85     touchPoints_.erase(touchId);
86     activeFingers_.remove(touchId);
87     if (IsNeedResetStatus()) {
88         ResetStatusOnFinish(isBlocked);
89     }
90 }
91 
CleanRecognizerState()92 void MultiFingersRecognizer::CleanRecognizerState()
93 {
94     if ((refereeState_ == RefereeState::SUCCEED ||
95         refereeState_ == RefereeState::FAIL ||
96         refereeState_ == RefereeState::DETECTING) &&
97         currentFingers_ == 0) {
98         refereeState_ = RefereeState::READY;
99         disposal_ = GestureDisposal::NONE;
100     }
101 }
102 
UpdateTouchPointWithAxisEvent(const AxisEvent & event)103 void MultiFingersRecognizer::UpdateTouchPointWithAxisEvent(const AxisEvent& event)
104 {
105     // Update touchPointInfo with axisEvent.
106     touchPoints_[event.id].id = event.id;
107     touchPoints_[event.id].x = event.x;
108     touchPoints_[event.id].y = event.y;
109     touchPoints_[event.id].screenX = event.screenX;
110     touchPoints_[event.id].screenY = event.screenY;
111     touchPoints_[event.id].sourceType = event.sourceType;
112     touchPoints_[event.id].sourceTool = event.sourceTool;
113     touchPoints_[event.id].originalId = event.originalId;
114     TouchPoint point;
115     point.id = event.id;
116     point.x = event.x;
117     point.y = event.y;
118     point.screenX = event.screenX;
119     point.screenY = event.screenY;
120     point.sourceTool = event.sourceTool;
121     point.originalId = event.originalId;
122     touchPoints_[event.id].pointers = { point };
123     touchPoints_[event.id].pointerEvent = event.pointerEvent;
124 }
125 
DumpGestureInfo() const126 std::string MultiFingersRecognizer::DumpGestureInfo() const
127 {
128     std::string infoStr;
129     infoStr.append("allowedTypes: [");
130     std::set<SourceTool> allowedTypes = {};
131     if (gestureInfo_) {
132         allowedTypes = gestureInfo_->GetAllowedTypes();
133     }
134     if (allowedTypes.empty()) {
135         infoStr.append("all]");
136         return infoStr;
137     }
138 
139     auto it = allowedTypes.begin();
140     while (it != allowedTypes.end()) {
141         infoStr.append(std::to_string(static_cast<int32_t>(*it)));
142         it++;
143         if (it != allowedTypes.end()) {
144             infoStr.append(", ");
145         }
146     }
147     infoStr.append("]");
148     return infoStr;
149 }
150 } // namespace OHOS::Ace::NG
151