• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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/components_ng/gestures/gesture_referee.h"
16 
17 #include "base/memory/ace_type.h"
18 #include "base/memory/referenced.h"
19 #include "base/utils/utils.h"
20 #include "core/components_ng/gestures/recognizers/gesture_recognizer.h"
21 #include "core/components_ng/gestures/recognizers/recognizer_group.h"
22 
23 namespace OHOS::Ace::NG {
24 
AddMember(const RefPtr<NGGestureRecognizer> & recognizer)25 void GestureScope::AddMember(const RefPtr<NGGestureRecognizer>& recognizer)
26 {
27     CHECK_NULL_VOID(recognizer);
28 
29     if (Existed(recognizer)) {
30         LOGW("gesture recognizer has already been added.");
31         return;
32     }
33 
34     recognizers_.emplace_back(recognizer);
35 }
36 
Existed(const RefPtr<NGGestureRecognizer> & recognizer)37 bool GestureScope::Existed(const RefPtr<NGGestureRecognizer>& recognizer)
38 {
39     CHECK_NULL_RETURN(recognizer, false);
40 
41     if (recognizers_.empty()) {
42         return false;
43     }
44 
45     auto result = std::find(recognizers_.cbegin(), recognizers_.cend(), recognizer);
46     return result != recognizers_.cend();
47 }
48 
CheckNeedBlocked(const RefPtr<NGGestureRecognizer> & recognizer)49 bool GestureScope::CheckNeedBlocked(const RefPtr<NGGestureRecognizer>& recognizer)
50 {
51     for (const auto& weak : recognizers_) {
52         auto member = weak.Upgrade();
53         if (member == recognizer) {
54             return false;
55         }
56 
57         if (member && member->GetRefereeState() == RefereeState::PENDING) {
58             return true;
59         }
60     }
61     return false;
62 }
63 
OnAcceptGesture(const RefPtr<NGGestureRecognizer> & recognizer)64 void GestureScope::OnAcceptGesture(const RefPtr<NGGestureRecognizer>& recognizer)
65 {
66     hasGestureAccepted_ = true;
67     for (const auto& weak : recognizers_) {
68         auto gesture = weak.Upgrade();
69         if (gesture == recognizer) {
70             continue;
71         }
72         if (gesture) {
73             gesture->OnRejected();
74         }
75     }
76     if (queryStateFunc_) {
77         queryStateFunc_(touchId_);
78     }
79 }
80 
UnBlockGesture()81 RefPtr<NGGestureRecognizer> GestureScope::UnBlockGesture()
82 {
83     auto iter =
84         std::find_if(std::begin(recognizers_), std::end(recognizers_), [](const WeakPtr<NGGestureRecognizer>& member) {
85             auto recognizer = member.Upgrade();
86             return recognizer && ((recognizer->GetRefereeState() == RefereeState::PENDING_BLOCKED) ||
87                                      (recognizer->GetRefereeState() == RefereeState::SUCCEED_BLOCKED));
88         });
89     if (iter == recognizers_.end()) {
90         LOGD("no blocked gesture in recognizers");
91         return nullptr;
92     }
93     return (*iter).Upgrade();
94 }
95 
IsPending(size_t touchId)96 bool GestureScope::IsPending(size_t touchId)
97 {
98     auto iter = std::find_if(
99         std::begin(recognizers_), std::end(recognizers_), [touchId](const WeakPtr<NGGestureRecognizer>& member) {
100             auto recognizer = member.Upgrade();
101             RefereeState state = RefereeState::READY;
102             if (recognizer) {
103                 state = recognizer->GetRefereeState();
104                 if (AceType::InstanceOf<RecognizerGroup>(recognizer)) {
105                     auto group = AceType::DynamicCast<RecognizerGroup>(recognizer);
106                     state = group->CheckStates(touchId);
107                 }
108             }
109             return recognizer && ((state == RefereeState::PENDING));
110         });
111     return iter != recognizers_.end();
112 }
113 
DectectAllDone(const RefPtr<NGGestureRecognizer> recognizer)114 bool DectectAllDone(const RefPtr<NGGestureRecognizer> recognizer)
115 {
116     RefereeState state = recognizer->GetRefereeState();
117     if (!AceType::InstanceOf<RecognizerGroup>(recognizer)) {
118         if (state != RefereeState::SUCCEED && state != RefereeState::SUCCEED_BLOCKED && state != RefereeState::FAIL) {
119             return false;
120         }
121     } else {
122         auto group = AceType::DynamicCast<RecognizerGroup>(recognizer);
123         for (const auto& item : group->GetGroupRecognizer()) {
124             bool ret = DectectAllDone(item);
125             if (!ret) {
126                 return false;
127             }
128         }
129     }
130     return true;
131 }
132 
QueryAllDone(size_t touchId)133 bool GestureScope::QueryAllDone(size_t touchId)
134 {
135     bool ret = true;
136     for (auto item : recognizers_) {
137         auto recognizer = item.Upgrade();
138         if (!recognizer) {
139             continue;
140         }
141         ret = DectectAllDone(recognizer);
142         if (ret == false) {
143             break;
144         }
145     }
146     return ret;
147 }
148 
Close(bool isBlocked)149 void GestureScope::Close(bool isBlocked)
150 {
151     LOGD("force close gesture scope of id %{public}d", static_cast<int32_t>(touchId_));
152     for (const auto& weak : recognizers_) {
153         auto recognizer = weak.Upgrade();
154         if (recognizer) {
155             recognizer->FinishReferee(static_cast<int32_t>(touchId_), isBlocked);
156         }
157     }
158 }
159 
AddGestureToScope(size_t touchId,const TouchTestResult & result)160 void GestureReferee::AddGestureToScope(size_t touchId, const TouchTestResult& result)
161 {
162     RefPtr<GestureScope> scope;
163     const auto iter = gestureScopes_.find(touchId);
164     if (iter != gestureScopes_.end()) {
165         LOGI("gesture scope of touch id %{public}d already exists.", static_cast<int32_t>(touchId));
166         scope = iter->second;
167     } else {
168         scope = MakeRefPtr<GestureScope>(touchId);
169         gestureScopes_.try_emplace(touchId, scope);
170     }
171     for (const auto& item : result) {
172         if (AceType::InstanceOf<NGGestureRecognizer>(item)) {
173             scope->AddMember(DynamicCast<NGGestureRecognizer>(item));
174             scope->SetQueryStateFunc(queryStateFunc_);
175         }
176     }
177 }
178 
CleanGestureScope(size_t touchId)179 void GestureReferee::CleanGestureScope(size_t touchId)
180 {
181     const auto iter = gestureScopes_.find(touchId);
182     if (iter != gestureScopes_.end()) {
183         const auto& scope = iter->second;
184         if (scope->IsPending(touchId)) {
185             scope->SetDelayClose();
186             return;
187         }
188         scope->Close();
189         gestureScopes_.erase(iter);
190     }
191 }
192 
QueryAllDone(size_t touchId)193 bool GestureReferee::QueryAllDone(size_t touchId)
194 {
195     bool ret = false;
196     const auto iter = gestureScopes_.find(touchId);
197     if (iter != gestureScopes_.end()) {
198         const auto& scope = iter->second;
199         ret = scope->QueryAllDone(touchId);
200     }
201     return ret;
202 }
203 
CheckSourceTypeChange(SourceType type,bool isAxis_)204 bool GestureReferee::CheckSourceTypeChange(SourceType type, bool isAxis_)
205 {
206     bool ret = false;
207     if (type != lastSourceType_) {
208         ret = true;
209         lastSourceType_ = type;
210     }
211     if (isAxis_ != lastIsAxis_) {
212         ret = true;
213         lastIsAxis_ = isAxis_;
214     }
215     return ret;
216 }
217 
CleanAll(bool isBlocked)218 void GestureReferee::CleanAll(bool isBlocked)
219 {
220     for (auto iter = gestureScopes_.begin(); iter != gestureScopes_.end(); iter++) {
221         iter->second->Close(isBlocked);
222     }
223     gestureScopes_.clear();
224 }
225 
Adjudicate(const RefPtr<NGGestureRecognizer> & recognizer,GestureDisposal disposal)226 void GestureReferee::Adjudicate(const RefPtr<NGGestureRecognizer>& recognizer, GestureDisposal disposal)
227 {
228     CHECK_NULL_VOID(recognizer);
229 
230     switch (disposal) {
231         case GestureDisposal::ACCEPT:
232             HandleAcceptDisposal(recognizer);
233             break;
234         case GestureDisposal::PENDING:
235             HandlePendingDisposal(recognizer);
236             break;
237         case GestureDisposal::REJECT:
238             HandleRejectDisposal(recognizer);
239             break;
240         default:
241             LOGW("handle known gesture disposal %{public}d", disposal);
242             break;
243     }
244 }
245 
HandleAcceptDisposal(const RefPtr<NGGestureRecognizer> & recognizer)246 void GestureReferee::HandleAcceptDisposal(const RefPtr<NGGestureRecognizer>& recognizer)
247 {
248     CHECK_NULL_VOID(recognizer);
249 
250     if (recognizer->GetRefereeState() == RefereeState::SUCCEED) {
251         return;
252     }
253 
254     bool isBlocked = false;
255     for (const auto& scope : gestureScopes_) {
256         if (scope.second->CheckNeedBlocked(recognizer)) {
257             isBlocked = true;
258             break;
259         }
260     }
261     if (isBlocked) {
262         recognizer->OnBlocked();
263         return;
264     }
265     auto prevState = recognizer->GetRefereeState();
266     recognizer->OnAccepted();
267     std::list<size_t> delayIds;
268     for (const auto& scope : gestureScopes_) {
269         scope.second->OnAcceptGesture(recognizer);
270     }
271     // clean delay task.
272     if (prevState == RefereeState::PENDING) {
273         auto iter = gestureScopes_.begin();
274         while (iter != gestureScopes_.end()) {
275             if (iter->second->IsDelayClosed()) {
276                 iter->second->Close();
277                 iter = gestureScopes_.erase(iter);
278             } else {
279                 ++iter;
280             }
281         }
282     }
283 }
284 
HandlePendingDisposal(const RefPtr<NGGestureRecognizer> & recognizer)285 void GestureReferee::HandlePendingDisposal(const RefPtr<NGGestureRecognizer>& recognizer)
286 {
287     CHECK_NULL_VOID(recognizer);
288 
289     if (recognizer->GetRefereeState() == RefereeState::PENDING) {
290         return;
291     }
292 
293     bool isBlocked = false;
294     for (const auto& scope : gestureScopes_) {
295         if (scope.second->CheckNeedBlocked(recognizer)) {
296             isBlocked = true;
297             break;
298         }
299     }
300     if (isBlocked) {
301         recognizer->OnBlocked();
302         return;
303     }
304     recognizer->OnPending();
305 }
306 
HandleRejectDisposal(const RefPtr<NGGestureRecognizer> & recognizer)307 void GestureReferee::HandleRejectDisposal(const RefPtr<NGGestureRecognizer>& recognizer)
308 {
309     CHECK_NULL_VOID(recognizer);
310 
311     if (recognizer->GetRefereeState() == RefereeState::FAIL) {
312         return;
313     }
314 
315     auto prevState = recognizer->GetRefereeState();
316     recognizer->OnRejected();
317     if (prevState != RefereeState::PENDING) {
318         return;
319     }
320     RefPtr<NGGestureRecognizer> newBlockRecognizer;
321     for (const auto& scope : gestureScopes_) {
322         newBlockRecognizer = scope.second->UnBlockGesture();
323         if (newBlockRecognizer) {
324             break;
325         }
326     }
327     if (newBlockRecognizer) {
328         if (newBlockRecognizer->GetRefereeState() == RefereeState::PENDING_BLOCKED) {
329             newBlockRecognizer->OnPending();
330         } else if (newBlockRecognizer->GetRefereeState() == RefereeState::SUCCEED_BLOCKED) {
331             newBlockRecognizer->OnAccepted();
332             for (const auto& scope : gestureScopes_) {
333                 scope.second->OnAcceptGesture(newBlockRecognizer);
334             }
335         }
336     }
337 
338     // clean delay task.
339     auto iter = gestureScopes_.begin();
340     while (iter != gestureScopes_.end()) {
341         if (iter->second->IsDelayClosed()) {
342             iter->second->Close();
343             iter = gestureScopes_.erase(iter);
344         } else {
345             ++iter;
346         }
347     }
348 }
349 
HasGestureAccepted(size_t touchId) const350 bool GestureReferee::HasGestureAccepted(size_t touchId) const
351 {
352     const auto& iter = gestureScopes_.find(touchId);
353     if (iter == gestureScopes_.end()) {
354         LOGI("gesture scope is not exist");
355         return false;
356     }
357 
358     const auto& scope = iter->second;
359     CHECK_NULL_RETURN(scope, false);
360     return scope->HasGestureAccepted();
361 }
362 
363 } // namespace OHOS::Ace::NG
364