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