• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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