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