1 /*
2 * Copyright (c) 2021 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/gestures/gesture_referee.h"
16
17 #include "core/gestures/click_recognizer.h"
18 #include "core/gestures/gesture_recognizer.h"
19
20 namespace OHOS::Ace {
21
AddMember(const RefPtr<GestureRecognizer> & recognizer)22 void GestureScope::AddMember(const RefPtr<GestureRecognizer>& recognizer)
23 {
24 if (!recognizer) {
25 LOGE("gesture recognizer is null, AddMember failed.");
26 return;
27 }
28
29 if (Existed(recognizer)) {
30 LOGW("gesture recognizer has already been added.");
31 return;
32 }
33
34 recognizer->SetRefereeState(RefereeState::DETECTING);
35
36 switch (recognizer->GetPriority()) {
37 case GesturePriority::Parallel:
38 parallelRecognizers_.emplace_back(recognizer);
39 break;
40 case GesturePriority::High:
41 highRecognizers_.emplace_back(recognizer);
42 break;
43 case GesturePriority::Low:
44 lowRecognizers_.emplace_back(recognizer);
45 break;
46 default:
47 LOGW("Add unknown type member %{public}d to referee", recognizer->GetPriority());
48 break;
49 }
50 }
51
DelMember(const RefPtr<GestureRecognizer> & recognizer)52 void GestureScope::DelMember(const RefPtr<GestureRecognizer>& recognizer)
53 {
54 if (!recognizer) {
55 LOGI("gesture recognizer is null, DelMember finish.");
56 return;
57 }
58
59 if (!Existed(recognizer)) {
60 LOGI("gesture recognizer is not existed when deleted.");
61 return;
62 }
63
64 RefereeState prevState = recognizer->GetRefereeState();
65 recognizer->SetRefereeState(RefereeState::DETECTING);
66
67 if (recognizer->GetPriority() == GesturePriority::Parallel) {
68 parallelRecognizers_.remove(recognizer);
69 return;
70 }
71
72 RemoveAndUnBlockGesture(prevState == RefereeState::PENDING, recognizer);
73 }
74
HandleGestureDisposal(const RefPtr<GestureRecognizer> & recognizer,const GestureDisposal disposal)75 void GestureScope::HandleGestureDisposal(const RefPtr<GestureRecognizer>& recognizer, const GestureDisposal disposal)
76 {
77 if (!Existed(recognizer)) {
78 LOGE("can not find the recognizer");
79 return;
80 }
81
82 GesturePriority priority = recognizer->GetPriority();
83 if (priority == GesturePriority::Parallel) {
84 HandleParallelDisposal(recognizer, disposal);
85 return;
86 }
87
88 switch (disposal) {
89 case GestureDisposal::ACCEPT:
90 HandleAcceptDisposal(recognizer);
91 break;
92 case GestureDisposal::PENDING:
93 HandlePendingDisposal(recognizer);
94 break;
95 case GestureDisposal::REJECT:
96 HandleRejectDisposal(recognizer);
97 break;
98 default:
99 LOGW("handle known gesture disposal %{public}d", disposal);
100 break;
101 }
102 }
103
HandleParallelDisposal(const RefPtr<GestureRecognizer> & recognizer,GestureDisposal disposal)104 void GestureScope::HandleParallelDisposal(const RefPtr<GestureRecognizer>& recognizer, GestureDisposal disposal)
105 {
106 if (disposal == GestureDisposal::REJECT) {
107 parallelRecognizers_.remove(recognizer);
108 recognizer->SetRefereeState(RefereeState::FAIL);
109 recognizer->OnRejected(touchId_);
110 } else if (disposal == GestureDisposal::ACCEPT) {
111 parallelRecognizers_.remove(recognizer);
112 recognizer->SetRefereeState(RefereeState::SUCCEED);
113 recognizer->OnAccepted(touchId_);
114 } else if (disposal == GestureDisposal::PENDING) {
115 recognizer->SetRefereeState(RefereeState::PENDING);
116 recognizer->OnPending(touchId_);
117 }
118 }
119
HandleAcceptDisposal(const RefPtr<GestureRecognizer> & recognizer)120 void GestureScope::HandleAcceptDisposal(const RefPtr<GestureRecognizer>& recognizer)
121 {
122 if (queryStateFunc_ && queryStateFunc_(touchId_)) {
123 LOGI("gesture has accepted in NG.");
124 recognizer->SetRefereeState(RefereeState::FAIL);
125 return;
126 }
127
128 if (CheckNeedBlocked(recognizer)) {
129 LOGI("gesture referee ready to notify block for %{public}s", AceType::TypeName(recognizer));
130 recognizer->SetRefereeState(RefereeState::BLOCKED);
131 return;
132 }
133
134 LOGI("gesture referee accept %{public}s of id %{public}zu", AceType::TypeName(recognizer), touchId_);
135 AcceptGesture(recognizer);
136 }
137
HandlePendingDisposal(const RefPtr<GestureRecognizer> & recognizer)138 void GestureScope::HandlePendingDisposal(const RefPtr<GestureRecognizer>& recognizer)
139 {
140 if (queryStateFunc_ && queryStateFunc_(touchId_)) {
141 LOGI("gesture has accepted in NG.");
142 recognizer->SetRefereeState(RefereeState::FAIL);
143 return;
144 }
145
146 if (CheckNeedBlocked(recognizer)) {
147 LOGI("gesture referee ready to notify block for %{public}s", AceType::TypeName(recognizer));
148 recognizer->SetRefereeState(RefereeState::BLOCKED);
149 return;
150 }
151
152 LOGI("gesture referee ready to notify pending for %{public}s", AceType::TypeName(recognizer));
153 recognizer->SetRefereeState(RefereeState::PENDING);
154 recognizer->OnPending(touchId_);
155 }
156
HandleRejectDisposal(const RefPtr<GestureRecognizer> & recognizer)157 void GestureScope::HandleRejectDisposal(const RefPtr<GestureRecognizer>& recognizer)
158 {
159 LOGI("gesture referee ready to notify reject for %{public}s", AceType::TypeName(recognizer));
160 RefereeState prevState = recognizer->GetRefereeState();
161 recognizer->SetRefereeState(RefereeState::FAIL);
162 recognizer->OnRejected(touchId_);
163 RemoveAndUnBlockGesture(prevState == RefereeState::PENDING, recognizer);
164 }
165
RemoveAndUnBlockGesture(bool isPrevPending,const WeakPtr<GestureRecognizer> & weakRecognizer)166 void GestureScope::RemoveAndUnBlockGesture(bool isPrevPending, const WeakPtr<GestureRecognizer>& weakRecognizer)
167 {
168 auto recognizer = weakRecognizer.Upgrade();
169 if (!recognizer) {
170 return;
171 }
172 if (recognizer->GetPriority() == GesturePriority::High) {
173 highRecognizers_.remove(recognizer);
174 if (highRecognizers_.empty()) {
175 UnBlockGesture(lowRecognizers_);
176 return;
177 }
178
179 if (isPrevPending) {
180 UnBlockGesture(highRecognizers_);
181 }
182 } else {
183 lowRecognizers_.remove(recognizer);
184 if (isPrevPending) {
185 UnBlockGesture(lowRecognizers_);
186 }
187 }
188 }
189
Existed(const RefPtr<GestureRecognizer> & recognizer)190 bool GestureScope::Existed(const RefPtr<GestureRecognizer>& recognizer)
191 {
192 if (!recognizer) {
193 LOGE("recognizer is null, AddGestureRecognizer failed.");
194 return false;
195 }
196
197 std::list<WeakPtr<GestureRecognizer>> members = GetMembersByRecognizer(recognizer);
198 if (members.empty()) {
199 return false;
200 }
201
202 auto result = std::find(members.cbegin(), members.cend(), recognizer);
203 return result != members.cend();
204 }
205
GetMembersByRecognizer(const RefPtr<GestureRecognizer> & recognizer)206 const std::list<WeakPtr<GestureRecognizer>>& GestureScope::GetMembersByRecognizer(
207 const RefPtr<GestureRecognizer>& recognizer)
208 {
209 switch (recognizer->GetPriority()) {
210 case GesturePriority::Low:
211 return lowRecognizers_;
212 case GesturePriority::High:
213 return highRecognizers_;
214 case GesturePriority::Parallel:
215 return parallelRecognizers_;
216 default:
217 return lowRecognizers_;
218 }
219 }
220
CheckNeedBlocked(const RefPtr<GestureRecognizer> & recognizer)221 bool GestureScope::CheckNeedBlocked(const RefPtr<GestureRecognizer>& recognizer)
222 {
223 if (recognizer->GetPriority() == GesturePriority::Low && !highRecognizers_.empty()) {
224 return true;
225 }
226
227 std::list<WeakPtr<GestureRecognizer>> members = GetMembersByRecognizer(recognizer);
228 for (const auto& member : members) {
229 if (member == recognizer) {
230 return false;
231 }
232
233 if (member.Upgrade() && member.Upgrade()->GetRefereeState() == RefereeState::PENDING) {
234 return true;
235 }
236 }
237
238 return false;
239 }
240
AcceptGesture(const RefPtr<GestureRecognizer> & recognizer)241 void GestureScope::AcceptGesture(const RefPtr<GestureRecognizer>& recognizer)
242 {
243 if (recognizer->GetPriority() == GesturePriority::Low) {
244 for (const auto& rejectedItem : lowRecognizers_) {
245 if (rejectedItem == recognizer) {
246 continue;
247 }
248 auto strongItem = rejectedItem.Upgrade();
249 if (strongItem) {
250 strongItem->OnRejected(touchId_);
251 strongItem->SetRefereeState(RefereeState::FAIL);
252 }
253 }
254 } else {
255 for (const auto& rejectedItem : highRecognizers_) {
256 if (rejectedItem == recognizer) {
257 continue;
258 }
259 auto strongItem = rejectedItem.Upgrade();
260 if (strongItem) {
261 strongItem->OnRejected(touchId_);
262 strongItem->SetRefereeState(RefereeState::FAIL);
263 }
264 }
265
266 for (const auto& rejectedItem : lowRecognizers_) {
267 if (rejectedItem == recognizer) {
268 continue;
269 }
270 auto strongItem = rejectedItem.Upgrade();
271 if (strongItem) {
272 strongItem->OnRejected(touchId_);
273 strongItem->SetRefereeState(RefereeState::FAIL);
274 }
275 }
276 }
277
278 recognizer->SetRefereeState(RefereeState::SUCCEED);
279 recognizer->OnAccepted(touchId_);
280 if (recognizer->GetPriority() == GesturePriority::Low) {
281 lowRecognizers_.clear();
282 } else {
283 highRecognizers_.clear();
284 lowRecognizers_.clear();
285 }
286 }
287
UnBlockGesture(std::list<WeakPtr<GestureRecognizer>> & members)288 void GestureScope::UnBlockGesture(std::list<WeakPtr<GestureRecognizer>>& members)
289 {
290 auto weakBlockedMember =
291 std::find_if(std::begin(members), std::end(members), [](const WeakPtr<GestureRecognizer>& member) {
292 return member.Upgrade() && member.Upgrade()->GetRefereeState() == RefereeState::BLOCKED;
293 });
294 if (weakBlockedMember == members.end()) {
295 return;
296 }
297 auto blockedMember = (*weakBlockedMember).Upgrade();
298 if (!blockedMember) {
299 LOGW("BlockedMember not exists.");
300 return;
301 }
302
303 if ((blockedMember)->GetDetectState() == DetectState::DETECTED) {
304 AcceptGesture(blockedMember);
305 return;
306 }
307
308 (blockedMember)->SetRefereeState(RefereeState::PENDING);
309 (blockedMember)->OnPending(touchId_);
310 }
311
ForceClose()312 void GestureScope::ForceClose()
313 {
314 for (const auto& weakRejectedItem : lowRecognizers_) {
315 auto rejectedItem = weakRejectedItem.Upgrade();
316 if (rejectedItem) {
317 rejectedItem->OnRejected(touchId_);
318 }
319 }
320 lowRecognizers_.clear();
321
322 for (const auto& weakRejectedItem : highRecognizers_) {
323 auto rejectedItem = weakRejectedItem.Upgrade();
324 if (rejectedItem) {
325 rejectedItem->OnRejected(touchId_);
326 }
327 }
328 highRecognizers_.clear();
329
330 for (const auto& weakRejectedItem : parallelRecognizers_) {
331 auto rejectedItem = weakRejectedItem.Upgrade();
332 if (rejectedItem) {
333 rejectedItem->OnRejected(touchId_);
334 }
335 }
336 parallelRecognizers_.clear();
337 }
338
IsPending() const339 bool GestureScope::IsPending() const
340 {
341 auto pendingMember = std::find_if(
342 std::begin(lowRecognizers_), std::end(lowRecognizers_), [](const WeakPtr<GestureRecognizer>& member) {
343 return member.Upgrade() && member.Upgrade()->GetRefereeState() == RefereeState::PENDING;
344 });
345 if (pendingMember != lowRecognizers_.end()) {
346 return true;
347 }
348
349 pendingMember = std::find_if(
350 std::begin(highRecognizers_), std::end(highRecognizers_), [](const WeakPtr<GestureRecognizer>& member) {
351 return member.Upgrade() && member.Upgrade()->GetRefereeState() == RefereeState::PENDING;
352 });
353 if (pendingMember != highRecognizers_.end()) {
354 return true;
355 }
356
357 pendingMember = std::find_if(
358 std::begin(parallelRecognizers_), std::end(parallelRecognizers_), [](const WeakPtr<GestureRecognizer>& member) {
359 return member.Upgrade() && member.Upgrade()->GetRefereeState() == RefereeState::PENDING;
360 });
361 return pendingMember != parallelRecognizers_.end();
362 }
363
AddGestureRecognizer(size_t touchId,const RefPtr<GestureRecognizer> & recognizer)364 void GestureReferee::AddGestureRecognizer(size_t touchId, const RefPtr<GestureRecognizer>& recognizer)
365 {
366 if (!recognizer) {
367 LOGE("recognizer is null, AddGestureRecognizer failed.");
368 return;
369 }
370 const auto iter = gestureScopes_.find(touchId);
371 if (iter != gestureScopes_.end()) {
372 iter->second.AddMember(recognizer);
373 } else {
374 GestureScope gestureScope(touchId);
375 gestureScope.AddMember(recognizer);
376 gestureScope.SetQueryStateFunc(queryStateFunc_);
377 gestureScopes_.try_emplace(touchId, std::move(gestureScope));
378 }
379 }
380
DelGestureRecognizer(size_t touchId,const RefPtr<GestureRecognizer> & recognizer)381 void GestureReferee::DelGestureRecognizer(size_t touchId, const RefPtr<GestureRecognizer>& recognizer)
382 {
383 if (!recognizer) {
384 LOGE("recognizer is null, DelGestureRecognizer failed.");
385 return;
386 }
387 const auto iter = gestureScopes_.find(touchId);
388 if (iter == gestureScopes_.end()) {
389 return;
390 }
391
392 iter->second.DelMember(recognizer);
393 }
394
CleanGestureScope(size_t touchId)395 void GestureReferee::CleanGestureScope(size_t touchId)
396 {
397 const auto iter = gestureScopes_.find(touchId);
398 if (iter != gestureScopes_.end()) {
399 if (iter->second.IsPending()) {
400 LOGE("gesture scope of touch id %{public}zu is pending, do not clean this.", touchId);
401 return;
402 }
403
404 if (!iter->second.IsEmpty()) {
405 iter->second.ForceClose();
406 }
407 gestureScopes_.erase(iter);
408 }
409 }
410
Adjudicate(size_t touchId,const RefPtr<GestureRecognizer> & recognizer,GestureDisposal disposal)411 void GestureReferee::Adjudicate(size_t touchId, const RefPtr<GestureRecognizer>& recognizer, GestureDisposal disposal)
412 {
413 if (!recognizer) {
414 LOGE("recognizer is null, Adjudicate failed.");
415 return;
416 }
417
418 const auto iter = gestureScopes_.find(touchId);
419 if (iter != gestureScopes_.end()) {
420 iter->second.HandleGestureDisposal(recognizer, disposal);
421 if (iter->second.IsEmpty()) {
422 gestureScopes_.erase(iter);
423 }
424 } else {
425 LOGE("fail to find the gesture scope for %{public}zu session id", touchId);
426 }
427 }
428
429 } // namespace OHOS::Ace
430