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/recognizer_group.h"
22
23 namespace OHOS::Ace::NG {
24
AddMember(const RefPtr<NGGestureRecognizer> & recognizer)25 void GestureScope::AddMember(const RefPtr<NGGestureRecognizer>& recognizer)
26 {
27 CHECK_NULL_VOID(recognizer);
28
29 if (Existed(recognizer)) {
30 LOGW("gesture recognizer has already been added.");
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 == recognizer) {
54 return false;
55 }
56
57 if (member && member->GetRefereeState() == RefereeState::PENDING) {
58 return true;
59 }
60 }
61 return false;
62 }
63
OnAcceptGesture(const RefPtr<NGGestureRecognizer> & recognizer)64 void GestureScope::OnAcceptGesture(const RefPtr<NGGestureRecognizer>& recognizer)
65 {
66 hasGestureAccepted_ = true;
67 for (const auto& weak : recognizers_) {
68 auto gesture = weak.Upgrade();
69 if (gesture == recognizer) {
70 continue;
71 }
72 if (gesture) {
73 gesture->OnRejected();
74 }
75 }
76 if (queryStateFunc_) {
77 queryStateFunc_(touchId_);
78 }
79 }
80
UnBlockGesture()81 RefPtr<NGGestureRecognizer> GestureScope::UnBlockGesture()
82 {
83 auto iter =
84 std::find_if(std::begin(recognizers_), std::end(recognizers_), [](const WeakPtr<NGGestureRecognizer>& member) {
85 auto recognizer = member.Upgrade();
86 return recognizer && ((recognizer->GetRefereeState() == RefereeState::PENDING_BLOCKED) ||
87 (recognizer->GetRefereeState() == RefereeState::SUCCEED_BLOCKED));
88 });
89 if (iter == recognizers_.end()) {
90 LOGD("no blocked gesture in recognizers");
91 return nullptr;
92 }
93 return (*iter).Upgrade();
94 }
95
IsPending(size_t touchId)96 bool GestureScope::IsPending(size_t touchId)
97 {
98 auto iter = std::find_if(
99 std::begin(recognizers_), std::end(recognizers_), [touchId](const WeakPtr<NGGestureRecognizer>& member) {
100 auto recognizer = member.Upgrade();
101 RefereeState state = RefereeState::READY;
102 if (recognizer) {
103 state = recognizer->GetRefereeState();
104 if (AceType::InstanceOf<RecognizerGroup>(recognizer)) {
105 auto group = AceType::DynamicCast<RecognizerGroup>(recognizer);
106 state = group->CheckStates(touchId);
107 }
108 }
109 return recognizer && ((state == RefereeState::PENDING));
110 });
111 return iter != recognizers_.end();
112 }
113
DectectAllDone(const RefPtr<NGGestureRecognizer> recognizer)114 bool DectectAllDone(const RefPtr<NGGestureRecognizer> recognizer)
115 {
116 RefereeState state = recognizer->GetRefereeState();
117 if (!AceType::InstanceOf<RecognizerGroup>(recognizer)) {
118 if (state != RefereeState::SUCCEED && state != RefereeState::SUCCEED_BLOCKED && state != RefereeState::FAIL) {
119 return false;
120 }
121 } else {
122 auto group = AceType::DynamicCast<RecognizerGroup>(recognizer);
123 for (const auto& item : group->GetGroupRecognizer()) {
124 bool ret = DectectAllDone(item);
125 if (!ret) {
126 return false;
127 }
128 }
129 }
130 return true;
131 }
132
QueryAllDone(size_t touchId)133 bool GestureScope::QueryAllDone(size_t touchId)
134 {
135 bool ret = true;
136 for (auto item : recognizers_) {
137 auto recognizer = item.Upgrade();
138 if (!recognizer) {
139 continue;
140 }
141 ret = DectectAllDone(recognizer);
142 if (ret == false) {
143 break;
144 }
145 }
146 return ret;
147 }
148
Close(bool isBlocked)149 void GestureScope::Close(bool isBlocked)
150 {
151 LOGD("force close gesture scope of id %{public}d", static_cast<int32_t>(touchId_));
152 for (const auto& weak : recognizers_) {
153 auto recognizer = weak.Upgrade();
154 if (recognizer) {
155 recognizer->FinishReferee(static_cast<int32_t>(touchId_), isBlocked);
156 }
157 }
158 }
159
AddGestureToScope(size_t touchId,const TouchTestResult & result)160 void GestureReferee::AddGestureToScope(size_t touchId, const TouchTestResult& result)
161 {
162 RefPtr<GestureScope> scope;
163 const auto iter = gestureScopes_.find(touchId);
164 if (iter != gestureScopes_.end()) {
165 LOGI("gesture scope of touch id %{public}d already exists.", static_cast<int32_t>(touchId));
166 scope = iter->second;
167 } else {
168 scope = MakeRefPtr<GestureScope>(touchId);
169 gestureScopes_.try_emplace(touchId, scope);
170 }
171 for (const auto& item : result) {
172 if (AceType::InstanceOf<NGGestureRecognizer>(item)) {
173 scope->AddMember(DynamicCast<NGGestureRecognizer>(item));
174 scope->SetQueryStateFunc(queryStateFunc_);
175 }
176 }
177 }
178
CleanGestureScope(size_t touchId)179 void GestureReferee::CleanGestureScope(size_t touchId)
180 {
181 const auto iter = gestureScopes_.find(touchId);
182 if (iter != gestureScopes_.end()) {
183 const auto& scope = iter->second;
184 if (scope->IsPending(touchId)) {
185 scope->SetDelayClose();
186 return;
187 }
188 scope->Close();
189 gestureScopes_.erase(iter);
190 }
191 }
192
QueryAllDone(size_t touchId)193 bool GestureReferee::QueryAllDone(size_t touchId)
194 {
195 bool ret = false;
196 const auto iter = gestureScopes_.find(touchId);
197 if (iter != gestureScopes_.end()) {
198 const auto& scope = iter->second;
199 ret = scope->QueryAllDone(touchId);
200 }
201 return ret;
202 }
203
CheckSourceTypeChange(SourceType type,bool isAxis_)204 bool GestureReferee::CheckSourceTypeChange(SourceType type, bool isAxis_)
205 {
206 bool ret = false;
207 if (type != lastSourceType_) {
208 ret = true;
209 lastSourceType_ = type;
210 }
211 if (isAxis_ != lastIsAxis_) {
212 ret = true;
213 lastIsAxis_ = isAxis_;
214 }
215 return ret;
216 }
217
CleanAll(bool isBlocked)218 void GestureReferee::CleanAll(bool isBlocked)
219 {
220 for (auto iter = gestureScopes_.begin(); iter != gestureScopes_.end(); iter++) {
221 iter->second->Close(isBlocked);
222 }
223 gestureScopes_.clear();
224 }
225
Adjudicate(const RefPtr<NGGestureRecognizer> & recognizer,GestureDisposal disposal)226 void GestureReferee::Adjudicate(const RefPtr<NGGestureRecognizer>& recognizer, GestureDisposal disposal)
227 {
228 CHECK_NULL_VOID(recognizer);
229
230 switch (disposal) {
231 case GestureDisposal::ACCEPT:
232 HandleAcceptDisposal(recognizer);
233 break;
234 case GestureDisposal::PENDING:
235 HandlePendingDisposal(recognizer);
236 break;
237 case GestureDisposal::REJECT:
238 HandleRejectDisposal(recognizer);
239 break;
240 default:
241 LOGW("handle known gesture disposal %{public}d", disposal);
242 break;
243 }
244 }
245
HandleAcceptDisposal(const RefPtr<NGGestureRecognizer> & recognizer)246 void GestureReferee::HandleAcceptDisposal(const RefPtr<NGGestureRecognizer>& recognizer)
247 {
248 CHECK_NULL_VOID(recognizer);
249
250 if (recognizer->GetRefereeState() == RefereeState::SUCCEED) {
251 return;
252 }
253
254 bool isBlocked = false;
255 for (const auto& scope : gestureScopes_) {
256 if (scope.second->CheckNeedBlocked(recognizer)) {
257 isBlocked = true;
258 break;
259 }
260 }
261 if (isBlocked) {
262 recognizer->OnBlocked();
263 return;
264 }
265 auto prevState = recognizer->GetRefereeState();
266 recognizer->OnAccepted();
267 std::list<size_t> delayIds;
268 for (const auto& scope : gestureScopes_) {
269 scope.second->OnAcceptGesture(recognizer);
270 }
271 // clean delay task.
272 if (prevState == RefereeState::PENDING) {
273 auto iter = gestureScopes_.begin();
274 while (iter != gestureScopes_.end()) {
275 if (iter->second->IsDelayClosed()) {
276 iter->second->Close();
277 iter = gestureScopes_.erase(iter);
278 } else {
279 ++iter;
280 }
281 }
282 }
283 }
284
HandlePendingDisposal(const RefPtr<NGGestureRecognizer> & recognizer)285 void GestureReferee::HandlePendingDisposal(const RefPtr<NGGestureRecognizer>& recognizer)
286 {
287 CHECK_NULL_VOID(recognizer);
288
289 if (recognizer->GetRefereeState() == RefereeState::PENDING) {
290 return;
291 }
292
293 bool isBlocked = false;
294 for (const auto& scope : gestureScopes_) {
295 if (scope.second->CheckNeedBlocked(recognizer)) {
296 isBlocked = true;
297 break;
298 }
299 }
300 if (isBlocked) {
301 recognizer->OnBlocked();
302 return;
303 }
304 recognizer->OnPending();
305 }
306
HandleRejectDisposal(const RefPtr<NGGestureRecognizer> & recognizer)307 void GestureReferee::HandleRejectDisposal(const RefPtr<NGGestureRecognizer>& recognizer)
308 {
309 CHECK_NULL_VOID(recognizer);
310
311 if (recognizer->GetRefereeState() == RefereeState::FAIL) {
312 return;
313 }
314
315 auto prevState = recognizer->GetRefereeState();
316 recognizer->OnRejected();
317 if (prevState != RefereeState::PENDING) {
318 return;
319 }
320 RefPtr<NGGestureRecognizer> newBlockRecognizer;
321 for (const auto& scope : gestureScopes_) {
322 newBlockRecognizer = scope.second->UnBlockGesture();
323 if (newBlockRecognizer) {
324 break;
325 }
326 }
327 if (newBlockRecognizer) {
328 if (newBlockRecognizer->GetRefereeState() == RefereeState::PENDING_BLOCKED) {
329 newBlockRecognizer->OnPending();
330 } else if (newBlockRecognizer->GetRefereeState() == RefereeState::SUCCEED_BLOCKED) {
331 newBlockRecognizer->OnAccepted();
332 for (const auto& scope : gestureScopes_) {
333 scope.second->OnAcceptGesture(newBlockRecognizer);
334 }
335 }
336 }
337
338 // clean delay task.
339 auto iter = gestureScopes_.begin();
340 while (iter != gestureScopes_.end()) {
341 if (iter->second->IsDelayClosed()) {
342 iter->second->Close();
343 iter = gestureScopes_.erase(iter);
344 } else {
345 ++iter;
346 }
347 }
348 }
349
HasGestureAccepted(size_t touchId) const350 bool GestureReferee::HasGestureAccepted(size_t touchId) const
351 {
352 const auto& iter = gestureScopes_.find(touchId);
353 if (iter == gestureScopes_.end()) {
354 LOGI("gesture scope is not exist");
355 return false;
356 }
357
358 const auto& scope = iter->second;
359 CHECK_NULL_RETURN(scope, false);
360 return scope->HasGestureAccepted();
361 }
362
363 } // namespace OHOS::Ace::NG
364