1 /*
2  * Copyright (c) 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/recognizer_group.h"
17 
18 #include "base/memory/ace_type.h"
19 #include "base/memory/referenced.h"
20 #include "base/utils/utils.h"
21 #include "core/components_ng/base/frame_node.h"
22 #include "core/components_ng/gestures/recognizers/gesture_recognizer.h"
23 #include "core/components_ng/gestures/gesture_group.h"
24 
25 namespace OHOS::Ace::NG {
26 
OnBeginGestureReferee(int32_t touchId,bool needUpdateChild)27 void RecognizerGroup::OnBeginGestureReferee(int32_t touchId, bool needUpdateChild)
28 {
29     MultiFingersRecognizer::OnBeginGestureReferee(touchId);
30     if (!needUpdateChild) {
31         return;
32     }
33     for (const auto& child : recognizers_) {
34         if (child) {
35             child->BeginReferee(touchId, needUpdateChild);
36         }
37     }
38 }
39 
CreateGestureFromRecognizer() const40 RefPtr<Gesture> RecognizerGroup::CreateGestureFromRecognizer() const
41 {
42     GestureMode mode = GetGestureMode();
43     RefPtr<GestureGroup> gestureGroup = AceType::MakeRefPtr<GestureGroup>(mode);
44     for (const auto& child : recognizers_) {
45         if (!child) {
46             continue;
47         }
48         RefPtr<Gesture> gesture = child->CreateGestureFromRecognizer();
49         if (gesture) {
50             gestureGroup->AddGesture(gesture);
51         }
52     }
53     return gestureGroup;
54 }
55 
OnFinishGestureReferee(int32_t touchId,bool isBlocked)56 void RecognizerGroup::OnFinishGestureReferee(int32_t touchId, bool isBlocked)
57 {
58     for (const auto& child : recognizers_) {
59         if (child) {
60             child->FinishReferee(touchId, isBlocked);
61         }
62     }
63     MultiFingersRecognizer::OnFinishGestureReferee(touchId, isBlocked);
64 }
65 
GetGroupRecognizer()66 const std::list<RefPtr<NGGestureRecognizer>>& RecognizerGroup::GetGroupRecognizer()
67 {
68     return recognizers_;
69 }
70 
AddChildren(const std::list<RefPtr<NGGestureRecognizer>> & recognizers)71 void RecognizerGroup::AddChildren(const std::list<RefPtr<NGGestureRecognizer>>& recognizers)
72 {
73     for (const auto& child : recognizers) {
74         if (child && !Existed(child) && child->SetGestureGroup(AceType::WeakClaim(this))) {
75             recognizers_.emplace_back(child);
76         }
77     }
78 }
79 
CheckStates(size_t touchId)80 RefereeState RecognizerGroup::CheckStates(size_t touchId)
81 {
82     int count = 0;
83     for (auto& recognizer : recognizers_) {
84         if (AceType::InstanceOf<MultiFingersRecognizer>(recognizer) && !recognizer->CheckTouchId(touchId)) {
85             continue;
86         }
87         if (!AceType::InstanceOf<RecognizerGroup>(recognizer)) {
88             if (recognizer->GetRefereeState() != RefereeState::SUCCEED_BLOCKED &&
89                 recognizer->GetRefereeState() != RefereeState::SUCCEED &&
90                 recognizer->GetRefereeState() != RefereeState::FAIL &&
91                 recognizer->GetRefereeState() != RefereeState::READY) {
92                 count++;
93                 break;
94             }
95             continue;
96         }
97         auto group = AceType::DynamicCast<RecognizerGroup>(recognizer);
98         if (group) {
99             auto state = group->CheckStates(touchId);
100             if (state == RefereeState::PENDING) {
101                 count++;
102                 break;
103             }
104         }
105     }
106     if (count > 0) {
107         return RefereeState::PENDING;
108     } else {
109         return RefereeState::READY;
110     }
111 }
112 
ForceReject()113 void RecognizerGroup::ForceReject()
114 {
115     for (auto& recognizer : recognizers_) {
116         if (!AceType::InstanceOf<RecognizerGroup>(recognizer)) {
117             if (recognizer->IsBridgeMode()) {
118                 continue;
119             }
120             if (recognizer->GetRefereeState() != RefereeState::SUCCEED_BLOCKED &&
121                 recognizer->GetRefereeState() != RefereeState::SUCCEED &&
122                 recognizer->GetRefereeState() != RefereeState::FAIL) {
123                 recognizer->OnRejected();
124                 recognizer->OnRejectBridgeObj();
125             }
126             continue;
127         }
128         auto group = AceType::DynamicCast<RecognizerGroup>(recognizer);
129         if (group) {
130             group->ForceReject();
131         }
132     }
133     if (GetRefereeState() != RefereeState::FAIL) {
134         OnRejected();
135     }
136 }
137 
Existed(const RefPtr<NGGestureRecognizer> & recognizer)138 bool RecognizerGroup::Existed(const RefPtr<NGGestureRecognizer>& recognizer)
139 {
140     CHECK_NULL_RETURN(recognizer, false);
141 
142     if (recognizers_.empty()) {
143         return false;
144     }
145     auto result = std::find(recognizers_.cbegin(), recognizers_.cend(), recognizer);
146     return result != recognizers_.cend();
147 }
148 
OnFlushTouchEventsBegin()149 void RecognizerGroup::OnFlushTouchEventsBegin()
150 {
151     for (const auto& recognizer : recognizers_) {
152         if (recognizer) {
153             recognizer->OnFlushTouchEventsBegin();
154         }
155     }
156 }
157 
OnFlushTouchEventsEnd()158 void RecognizerGroup::OnFlushTouchEventsEnd()
159 {
160     for (const auto& recognizer : recognizers_) {
161         if (recognizer) {
162             recognizer->OnFlushTouchEventsEnd();
163         }
164     }
165 }
166 
OnResetStatus()167 void RecognizerGroup::OnResetStatus()
168 {
169     MultiFingersRecognizer::OnResetStatus();
170     if (!remainChildOnResetStatus_) {
171         for (const auto& child : recognizers_) {
172             if (child) {
173                 child->SetGestureGroup(nullptr);
174                 child->ResetEventImportGestureGroup();
175             }
176         }
177         recognizers_.clear();
178     }
179 }
180 
CheckAllFailed()181 bool RecognizerGroup::CheckAllFailed()
182 {
183     auto notFailMember =
184         std::find_if(std::begin(recognizers_), std::end(recognizers_), [](const RefPtr<NGGestureRecognizer>& member) {
185             return member && member->GetRefereeState() != RefereeState::FAIL;
186         });
187 
188     return notFailMember == recognizers_.end();
189 }
190 
GroupAdjudicate(const RefPtr<NGGestureRecognizer> & recognizer,GestureDisposal disposal)191 void RecognizerGroup::GroupAdjudicate(const RefPtr<NGGestureRecognizer>& recognizer, GestureDisposal disposal)
192 {
193     disposal_ = disposal;
194     NGGestureRecognizer::BatchAdjudicate(recognizer, disposal);
195 }
196 
SetRecognizerInfoRecursively(const Offset & coordinateOffset,const RefPtr<NG::FrameNode> & node,const RefPtr<NG::TargetComponent> & targetComponent,const GetEventTargetImpl & getEventTargetImpl)197 void RecognizerGroup::SetRecognizerInfoRecursively(const Offset& coordinateOffset, const RefPtr<NG::FrameNode>& node,
198     const RefPtr<NG::TargetComponent>& targetComponent, const GetEventTargetImpl& getEventTargetImpl)
199 {
200     for (const auto& item : recognizers_) {
201         item->SetCoordinateOffset(coordinateOffset);
202         item->AttachFrameNode(WeakPtr<FrameNode>(node));
203         item->SetTargetComponent(targetComponent);
204         item->SetGetEventTargetImpl(getEventTargetImpl);
205         auto group = AceType::DynamicCast<RecognizerGroup>(item);
206         if (group) {
207             group->SetRecognizerInfoRecursively(coordinateOffset, node, targetComponent, getEventTargetImpl);
208         }
209     }
210 }
211 
AddHittedRecognizerType(std::map<std::string,std::list<TouchTestResultInfo>> & hittedRecognizerInfo)212 void RecognizerGroup::AddHittedRecognizerType(
213     std::map<std::string, std::list<TouchTestResultInfo>>& hittedRecognizerInfo)
214 {
215     for (const auto& item : recognizers_) {
216         if (AceType::InstanceOf<NG::MultiFingersRecognizer>(item) && !AceType::InstanceOf<NG::RecognizerGroup>(item)) {
217             auto node = item->GetAttachedNode().Upgrade();
218             if (!node) {
219                 hittedRecognizerInfo.emplace(AceType::TypeName(item), std::list<NG::TouchTestResultInfo>());
220                 continue;
221             }
222             auto frameNode = AceType::DynamicCast<NG::FrameNode>(node);
223             if (!frameNode) {
224                 hittedRecognizerInfo.emplace(AceType::TypeName(item), std::list<NG::TouchTestResultInfo>());
225                 continue;
226             }
227             hittedRecognizerInfo[AceType::TypeName(item)].emplace_back(NG::TouchTestResultInfo {
228                 frameNode->GetId(), frameNode->GetTag(), frameNode->GetInspectorIdValue("") });
229         }
230         auto group = AceType::DynamicCast<RecognizerGroup>(item);
231         if (group) {
232             group->AddHittedRecognizerType(hittedRecognizerInfo);
233         }
234     }
235 }
236 
CleanRecognizerState()237 void RecognizerGroup::CleanRecognizerState()
238 {
239     for (const auto& child : recognizers_) {
240         if (child) {
241             child->CleanRecognizerState();
242         }
243     }
244     if ((refereeState_ == RefereeState::SUCCEED ||
245         refereeState_ == RefereeState::FAIL ||
246         refereeState_ == RefereeState::DETECTING) &&
247         currentFingers_ == 0) {
248         refereeState_ = RefereeState::READY;
249         disposal_ = GestureDisposal::NONE;
250     }
251 }
252 
IsReady()253 bool RecognizerGroup::IsReady()
254 {
255     if (refereeState_ != RefereeState::READY) {
256         return false;
257     }
258     for (const auto& child : recognizers_) {
259         if (child && !child->IsReady()) {
260             return false;
261         }
262     }
263     return true;
264 }
265 } // namespace OHOS::Ace::NG
266