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 #include "core/components_ng/gestures/gesture_referee.h"
16 #include "recognizers/gesture_recognizer.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/gestures/recognizers/gesture_recognizer.h"
22 #include "core/components_ng/gestures/recognizers/parallel_recognizer.h"
23 #include "core/components_ng/gestures/recognizers/recognizer_group.h"
24 
25 namespace OHOS::Ace::NG {
26 
AddMember(const RefPtr<NGGestureRecognizer> & recognizer)27 void GestureScope::AddMember(const RefPtr<NGGestureRecognizer>& recognizer)
28 {
29     CHECK_NULL_VOID(recognizer);
30 
31     if (Existed(recognizer)) {
32         return;
33     }
34 
35     recognizers_.emplace_back(recognizer);
36 }
37 
Existed(const RefPtr<NGGestureRecognizer> & recognizer)38 bool GestureScope::Existed(const RefPtr<NGGestureRecognizer>& recognizer)
39 {
40     CHECK_NULL_RETURN(recognizer, false);
41 
42     if (recognizers_.empty()) {
43         return false;
44     }
45 
46     auto result = std::find(recognizers_.cbegin(), recognizers_.cend(), recognizer);
47     return result != recognizers_.cend();
48 }
49 
CheckNeedBlocked(const RefPtr<NGGestureRecognizer> & recognizer)50 bool GestureScope::CheckNeedBlocked(const RefPtr<NGGestureRecognizer>& recognizer)
51 {
52     for (const auto& weak : recognizers_) {
53         auto member = weak.Upgrade();
54         if (!member || member->GetRefereeState() != RefereeState::PENDING) {
55             continue;
56         }
57         if (member == recognizer) {
58             return false;
59         }
60         RefPtr<NGGestureRecognizer> group = member->GetGestureGroup().Upgrade();
61         while (group) {
62             if (group == recognizer) {
63                 return false;
64             }
65             group = group->GetGestureGroup().Upgrade();
66         }
67         return true;
68     }
69     return false;
70 }
71 
OnAcceptGesture(const RefPtr<NGGestureRecognizer> & recognizer)72 void GestureScope::OnAcceptGesture(const RefPtr<NGGestureRecognizer>& recognizer)
73 {
74     hasGestureAccepted_ = true;
75     for (const auto& weak : recognizers_) {
76         auto gesture = weak.Upgrade();
77         if (gesture == recognizer) {
78             continue;
79         }
80         if (!gesture || gesture->IsBridgeMode()) {
81             continue;
82         }
83         gesture->OnRejected();
84         gesture->OnRejectBridgeObj();
85     }
86     if (queryStateFunc_) {
87         queryStateFunc_(touchId_);
88     }
89 }
90 
UnBlockGesture()91 RefPtr<NGGestureRecognizer> GestureScope::UnBlockGesture()
92 {
93     auto iter =
94         std::find_if(std::begin(recognizers_), std::end(recognizers_), [](const WeakPtr<NGGestureRecognizer>& member) {
95             auto recognizer = member.Upgrade();
96             return recognizer && ((recognizer->GetRefereeState() == RefereeState::PENDING_BLOCKED) ||
97                                      (recognizer->GetRefereeState() == RefereeState::SUCCEED_BLOCKED));
98         });
99     if (iter == recognizers_.end()) {
100         return nullptr;
101     }
102     return (*iter).Upgrade();
103 }
104 
IsPending(size_t touchId)105 bool GestureScope::IsPending(size_t touchId)
106 {
107     auto iter = std::find_if(
108         std::begin(recognizers_), std::end(recognizers_), [touchId](const WeakPtr<NGGestureRecognizer>& member) {
109             auto recognizer = member.Upgrade();
110             RefereeState state = RefereeState::READY;
111             if (recognizer) {
112                 state = recognizer->GetRefereeState();
113                 if (AceType::InstanceOf<RecognizerGroup>(recognizer)) {
114                     auto group = AceType::DynamicCast<RecognizerGroup>(recognizer);
115                     state = group->CheckStates(touchId);
116                 }
117             }
118             return recognizer && ((state == RefereeState::PENDING));
119         });
120     return iter != recognizers_.end();
121 }
122 
DectectAllDone(const RefPtr<NGGestureRecognizer> recognizer)123 bool DectectAllDone(const RefPtr<NGGestureRecognizer> recognizer)
124 {
125     RefereeState state = recognizer->GetRefereeState();
126     if (!AceType::InstanceOf<RecognizerGroup>(recognizer)) {
127         if (state != RefereeState::SUCCEED && state != RefereeState::SUCCEED_BLOCKED &&
128             state != RefereeState::FAIL && state != RefereeState::READY &&
129             state != RefereeState::DETECTING) {
130             return false;
131         }
132     } else {
133         auto group = AceType::DynamicCast<RecognizerGroup>(recognizer);
134         for (const auto& item : group->GetGroupRecognizer()) {
135             bool ret = DectectAllDone(item);
136             if (!ret) {
137                 return false;
138             }
139         }
140     }
141     return true;
142 }
143 
QueryAllDone(size_t touchId)144 bool GestureScope::QueryAllDone(size_t touchId)
145 {
146     bool ret = true;
147     for (auto item : recognizers_) {
148         auto recognizer = item.Upgrade();
149         if (!recognizer) {
150             continue;
151         }
152         ret = DectectAllDone(recognizer);
153         if (ret == false) {
154             break;
155         }
156     }
157     return ret;
158 }
159 
Close(bool isBlocked)160 void GestureScope::Close(bool isBlocked)
161 {
162     for (const auto& weak : recognizers_) {
163         auto recognizer = weak.Upgrade();
164         if (recognizer) {
165             auto weakGroup = recognizer->GetGestureGroup();
166             auto group = weakGroup.Upgrade();
167             while (group) {
168                 recognizer = group;
169                 weakGroup = group->GetGestureGroup();
170                 group = weakGroup.Upgrade();
171             }
172             recognizer->FinishReferee(static_cast<int32_t>(touchId_), isBlocked);
173         }
174     }
175 }
176 
CheckRecognizer(const RefPtr<NGGestureRecognizer> & recognizer)177 static bool CheckRecognizer(const RefPtr<NGGestureRecognizer>& recognizer)
178 {
179     if (!recognizer) {
180         return false;
181     }
182     auto group = AceType::DynamicCast<RecognizerGroup>(recognizer);
183     if (!group) {
184         return recognizer->GetRefereeState() == RefereeState::PENDING;
185     }
186     auto children = group->GetGroupRecognizer();
187     for (auto iter = children.begin(); iter != children.end(); ++iter) {
188         if (CheckRecognizer(*iter)) {
189             return true;
190         }
191     }
192     return group->CheckGroupState();
193 }
194 
CheckRecognizerState()195 bool GestureScope::CheckRecognizerState()
196 {
197     for (auto& weak : recognizers_) {
198         auto recognizer = weak.Upgrade();
199         if (CheckRecognizer(recognizer)) {
200             return true;
201         }
202     }
203     return false;
204 }
205 
IsReady()206 bool GestureScope::IsReady()
207 {
208     for (const auto& weak : recognizers_) {
209         auto recognizer = weak.Upgrade();
210         if (recognizer && !recognizer->IsReady()) {
211             return false;
212         }
213     }
214     return true;
215 }
216 
HasFailRecognizer()217 bool GestureScope::HasFailRecognizer()
218 {
219     for (const auto& weak : recognizers_) {
220         auto recognizer = weak.Upgrade();
221         if (recognizer && recognizer->GetRefereeState() == RefereeState::FAIL) {
222             return true;
223         }
224     }
225     return false;
226 }
227 
ForceCleanGestureScope()228 void GestureScope::ForceCleanGestureScope()
229 {
230     for (const auto& weak : recognizers_) {
231         auto recognizer = weak.Upgrade();
232         if (recognizer) {
233             recognizer->ForceCleanRecognizer();
234         }
235     }
236     recognizers_.clear();
237 }
238 
ForceCleanGestureScopeState()239 void GestureScope::ForceCleanGestureScopeState()
240 {
241     for (const auto& weak : recognizers_) {
242         auto recognizer = weak.Upgrade();
243         if (recognizer) {
244             recognizer->ForceCleanRecognizer();
245         }
246     }
247 }
248 
CleanGestureScopeState()249 void GestureScope::CleanGestureScopeState()
250 {
251     for (const auto& weak : recognizers_) {
252         auto recognizer = weak.Upgrade();
253         auto multiFingerRecognizer = AceType::DynamicCast<MultiFingersRecognizer>(recognizer);
254         if (multiFingerRecognizer && multiFingerRecognizer->CheckTouchId(touchId_) &&
255             multiFingerRecognizer->GetTouchPointsSize() == 1) {
256             multiFingerRecognizer->CleanRecognizerState();
257         }
258     }
259 }
260 
AddGestureToScope(size_t touchId,const TouchTestResult & result)261 void GestureReferee::AddGestureToScope(size_t touchId, const TouchTestResult& result)
262 {
263     RefPtr<GestureScope> scope;
264     const auto iter = gestureScopes_.find(touchId);
265     if (iter != gestureScopes_.end()) {
266         scope = iter->second;
267     } else {
268         scope = MakeRefPtr<GestureScope>(touchId);
269         gestureScopes_.try_emplace(touchId, scope);
270     }
271     for (const auto& item : result) {
272         if (AceType::InstanceOf<NGGestureRecognizer>(item)) {
273             scope->AddMember(DynamicCast<NGGestureRecognizer>(item));
274             scope->SetQueryStateFunc(queryStateFunc_);
275         }
276     }
277 }
278 
CleanGestureScope(size_t touchId)279 void GestureReferee::CleanGestureScope(size_t touchId)
280 {
281     const auto iter = gestureScopes_.find(touchId);
282     if (iter != gestureScopes_.end()) {
283         const auto& scope = iter->second;
284         if (scope->IsPending(touchId)) {
285             scope->SetDelayClose();
286             return;
287         }
288         scope->Close();
289         gestureScopes_.erase(iter);
290     }
291 }
292 
QueryAllDone(size_t touchId)293 bool GestureReferee::QueryAllDone(size_t touchId)
294 {
295     bool ret = true;
296     const auto iter = gestureScopes_.find(touchId);
297     if (iter != gestureScopes_.end()) {
298         const auto& scope = iter->second;
299         ret = scope->QueryAllDone(touchId);
300     }
301     return ret;
302 }
303 
QueryAllDone()304 bool GestureReferee::QueryAllDone()
305 {
306     for (auto iter = gestureScopes_.begin(); iter != gestureScopes_.end(); ++iter) {
307         if (!iter->second->QueryAllDone(iter->first)) {
308             return false;
309         }
310     }
311     return true;
312 }
313 
CheckEventTypeChange(SourceType type,bool isAxis) const314 bool GestureReferee::CheckEventTypeChange(SourceType type, bool isAxis) const
315 {
316     bool ret = false;
317     if (!isAxis && lastIsAxis_ && type == SourceType::TOUCH) {
318         ret = true;
319     }
320     return ret;
321 }
322 
CheckSourceTypeChange(SourceType type,bool isAxis_)323 bool GestureReferee::CheckSourceTypeChange(SourceType type, bool isAxis_)
324 {
325     bool ret = false;
326     if (type != lastSourceType_) {
327         ret = true;
328         lastSourceType_ = type;
329     }
330     if (isAxis_ != lastIsAxis_) {
331         ret = true;
332         lastIsAxis_ = isAxis_;
333     }
334     return ret;
335 }
336 
CleanAll(bool isBlocked)337 void GestureReferee::CleanAll(bool isBlocked)
338 {
339     for (auto iter = gestureScopes_.begin(); iter != gestureScopes_.end(); iter++) {
340         iter->second->Close(isBlocked);
341     }
342     gestureScopes_.clear();
343 }
344 
CleanRedundanceScope()345 void GestureReferee::CleanRedundanceScope()
346 {
347     for (auto iter = gestureScopes_.begin(); iter != gestureScopes_.end(); iter++) {
348         if (iter->second->CheckRecognizerState()) {
349             continue;
350         }
351         iter->second->Close();
352     }
353 }
354 
IsReady()355 bool GestureReferee::IsReady()
356 {
357     for (auto iter = gestureScopes_.begin(); iter != gestureScopes_.end(); iter++) {
358         if (!iter->second->IsReady()) {
359             return false;
360         }
361     }
362     return true;
363 }
364 
HasFailRecognizer(int32_t touchId)365 bool GestureReferee::HasFailRecognizer(int32_t touchId)
366 {
367     const auto& iter = gestureScopes_.find(touchId);
368     if (iter == gestureScopes_.end()) {
369         return false;
370     }
371 
372     const auto& scope = iter->second;
373     CHECK_NULL_RETURN(scope, false);
374 
375     return scope->HasFailRecognizer();
376 }
377 
ForceCleanGestureReferee()378 void GestureReferee::ForceCleanGestureReferee()
379 {
380     for (auto iter = gestureScopes_.begin(); iter != gestureScopes_.end(); iter++) {
381         iter->second->ForceCleanGestureScope();
382     }
383     gestureScopes_.clear();
384 }
385 
ForceCleanGestureRefereeState()386 void GestureReferee::ForceCleanGestureRefereeState()
387 {
388     for (auto iter = gestureScopes_.begin(); iter != gestureScopes_.end(); iter++) {
389         iter->second->ForceCleanGestureScopeState();
390     }
391 }
392 
CleanGestureRefereeState(int32_t touchId)393 void GestureReferee::CleanGestureRefereeState(int32_t touchId)
394 {
395     const auto& iter = gestureScopes_.find(touchId);
396     if (iter == gestureScopes_.end()) {
397         return;
398     }
399 
400     const auto& scope = iter->second;
401     CHECK_NULL_VOID(scope);
402 
403     scope->CleanGestureScopeState();
404 }
405 
Adjudicate(const RefPtr<NGGestureRecognizer> & recognizer,GestureDisposal disposal)406 void GestureReferee::Adjudicate(const RefPtr<NGGestureRecognizer>& recognizer, GestureDisposal disposal)
407 {
408     CHECK_NULL_VOID(recognizer);
409 
410     switch (disposal) {
411         case GestureDisposal::ACCEPT:
412             HandleAcceptDisposal(recognizer);
413             break;
414         case GestureDisposal::PENDING:
415             HandlePendingDisposal(recognizer);
416             break;
417         case GestureDisposal::REJECT:
418             HandleRejectDisposal(recognizer);
419             break;
420         default:
421             break;
422     }
423 }
424 
HandleAcceptDisposal(const RefPtr<NGGestureRecognizer> & recognizer)425 void GestureReferee::HandleAcceptDisposal(const RefPtr<NGGestureRecognizer>& recognizer)
426 {
427     CHECK_NULL_VOID(recognizer);
428 
429     if (recognizer->GetRefereeState() == RefereeState::SUCCEED) {
430         return;
431     }
432 
433     bool isBlocked = false;
434     for (const auto& scope : gestureScopes_) {
435         if (scope.second->CheckNeedBlocked(recognizer)) {
436             isBlocked = true;
437             break;
438         }
439     }
440     if (isBlocked) {
441         recognizer->OnBlocked();
442         return;
443     }
444     recognizer->AboutToAccept();
445     for (const auto& scope : gestureScopes_) {
446         scope.second->OnAcceptGesture(recognizer);
447     }
448 }
449 
HandlePendingDisposal(const RefPtr<NGGestureRecognizer> & recognizer)450 void GestureReferee::HandlePendingDisposal(const RefPtr<NGGestureRecognizer>& recognizer)
451 {
452     CHECK_NULL_VOID(recognizer);
453 
454     if (recognizer->GetRefereeState() == RefereeState::PENDING) {
455         return;
456     }
457 
458     bool isBlocked = false;
459     for (const auto& scope : gestureScopes_) {
460         if (scope.second->CheckNeedBlocked(recognizer)) {
461             isBlocked = true;
462             break;
463         }
464     }
465     if (isBlocked) {
466         recognizer->OnBlocked();
467         return;
468     }
469     recognizer->OnPending();
470 }
471 
HandleRejectDisposal(const RefPtr<NGGestureRecognizer> & recognizer)472 void GestureReferee::HandleRejectDisposal(const RefPtr<NGGestureRecognizer>& recognizer)
473 {
474     CHECK_NULL_VOID(recognizer);
475 
476     if (recognizer->GetRefereeState() == RefereeState::FAIL) {
477         return;
478     }
479 
480     auto prevState = recognizer->GetRefereeState();
481     recognizer->OnRejected();
482     if (prevState != RefereeState::PENDING) {
483         return;
484     }
485     RefPtr<NGGestureRecognizer> newBlockRecognizer;
486     for (const auto& scope : gestureScopes_) {
487         newBlockRecognizer = scope.second->UnBlockGesture();
488         if (newBlockRecognizer) {
489             break;
490         }
491     }
492     if (newBlockRecognizer) {
493         if (newBlockRecognizer->GetRefereeState() == RefereeState::PENDING_BLOCKED) {
494             newBlockRecognizer->OnPending();
495         } else if (newBlockRecognizer->GetRefereeState() == RefereeState::SUCCEED_BLOCKED) {
496             newBlockRecognizer->AboutToAccept();
497             for (const auto& scope : gestureScopes_) {
498                 scope.second->OnAcceptGesture(newBlockRecognizer);
499             }
500         }
501     }
502 }
503 
HasGestureAccepted(size_t touchId) const504 bool GestureReferee::HasGestureAccepted(size_t touchId) const
505 {
506     const auto& iter = gestureScopes_.find(touchId);
507     if (iter == gestureScopes_.end()) {
508         return false;
509     }
510 
511     const auto& scope = iter->second;
512     CHECK_NULL_RETURN(scope, false);
513     return scope->HasGestureAccepted();
514 }
515 
516 } // namespace OHOS::Ace::NG
517