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