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