• 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     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