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