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