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 
16 #include "core/gestures/timeout_recognizer.h"
17 
18 namespace OHOS::Ace {
SingleChildGestureRecognizer(WeakPtr<PipelineBase> context)19 SingleChildGestureRecognizer::SingleChildGestureRecognizer(WeakPtr<PipelineBase> context)
20     : context_(std::move(context))
21 {
22 }
23 
SingleChildGestureRecognizer(WeakPtr<PipelineBase> context,RefPtr<GestureRecognizer> child)24 SingleChildGestureRecognizer::SingleChildGestureRecognizer(WeakPtr<PipelineBase> context,
25     RefPtr<GestureRecognizer> child)
26     : child_(std::move(child)),
27     context_(std::move(context))
28 {
29     child_->SetGestureGroup(AceType::WeakClaim(this));
30     child_->SetIsExternalGesture(true);
31 }
32 
~SingleChildGestureRecognizer()33 SingleChildGestureRecognizer::~SingleChildGestureRecognizer()
34 {
35 }
36 
SetChild(RefPtr<GestureRecognizer> recognizer)37 void SingleChildGestureRecognizer::SetChild(RefPtr<GestureRecognizer> recognizer)
38 {
39     child_ = recognizer;
40     child_->SetGestureGroup(AceType::WeakClaim(this));
41     child_->SetIsExternalGesture(true);
42 }
43 
ReconcileFrom(const RefPtr<GestureRecognizer> & recognizer)44 bool SingleChildGestureRecognizer::ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer)
45 {
46     auto rhs = AceType::DynamicCast<SingleChildGestureRecognizer>(recognizer);
47     if (!rhs) {
48         return false;
49     }
50 
51     if (child_ == nullptr || rhs->child_ == nullptr) {
52         return false;
53     }
54 
55     if (!child_->ReconcileFrom(rhs->GetChild())) {
56         return false;
57     }
58 
59     return MultiFingersRecognizer::ReconcileFrom(recognizer);
60 }
61 
AddToReferee(size_t touchId,const RefPtr<GestureRecognizer> & recognizer)62 void SingleChildGestureRecognizer::AddToReferee(size_t touchId, const RefPtr<GestureRecognizer>& recognizer)
63 {
64     MultiFingersRecognizer::AddToReferee(touchId, AceType::Claim(this));
65 }
66 
DelFromReferee(size_t touchId,const RefPtr<GestureRecognizer> & recognizer)67 void SingleChildGestureRecognizer::DelFromReferee(size_t touchId, const RefPtr<GestureRecognizer>& recognizer)
68 {
69     MultiFingersRecognizer::DelFromReferee(touchId, AceType::Claim(this));
70 }
71 
GetChild() const72 RefPtr<GestureRecognizer> SingleChildGestureRecognizer::GetChild() const
73 {
74     return child_;
75 }
76 
TimeoutRecognizer(WeakPtr<PipelineBase> context,std::chrono::duration<float> timeout)77 TimeoutRecognizer::TimeoutRecognizer(WeakPtr<PipelineBase> context,
78     std::chrono::duration<float> timeout)
79     : SingleChildGestureRecognizer(context),
80     context_(context),
81     timeout_(timeout)
82 {
83 }
84 
TimeoutRecognizer(WeakPtr<PipelineBase> context,RefPtr<GestureRecognizer> child,std::chrono::duration<float> timeout)85 TimeoutRecognizer::TimeoutRecognizer(WeakPtr<PipelineBase> context,
86     RefPtr<GestureRecognizer> child, std::chrono::duration<float> timeout)
87     : SingleChildGestureRecognizer(context, std::move(child)),
88     context_(context),
89     timeout_(timeout)
90 {
91 }
92 
OnAccepted(size_t touchId)93 void TimeoutRecognizer::OnAccepted(size_t touchId)
94 {
95     start_.reset();
96     if (GetChild()->GetDetectState() == DetectState::DETECTED) {
97         GetChild()->SetCoordinateOffset(coordinateOffset_);
98         GetChild()->OnAccepted(touchId);
99     }
100 
101     SingleChildGestureRecognizer::OnAccepted(touchId);
102 }
103 
OnRejected(size_t touchId)104 void TimeoutRecognizer::OnRejected(size_t touchId)
105 {
106     GetChild()->OnRejected(touchId);
107 
108     SingleChildGestureRecognizer::OnRejected(touchId);
109 }
110 
ReconcileFrom(const RefPtr<GestureRecognizer> & recognizer)111 bool TimeoutRecognizer::ReconcileFrom(const RefPtr<GestureRecognizer>& recognizer)
112 {
113     auto rhs = AceType::DynamicCast<TimeoutRecognizer>(recognizer);
114     if (!rhs) {
115         return false;
116     }
117 
118     timeout_ = rhs->timeout_;
119 
120     return SingleChildGestureRecognizer::ReconcileFrom(recognizer);
121 }
122 
BatchAdjudicate(const std::set<size_t> & touchIds,const RefPtr<GestureRecognizer> & recognizer,GestureDisposal disposal)123 void TimeoutRecognizer::BatchAdjudicate(const std::set<size_t>& touchIds,
124     const RefPtr<GestureRecognizer>& recognizer, GestureDisposal disposal)
125 {
126     if (disposal == GestureDisposal::ACCEPT) {
127         start_.reset();
128         touchIds_.clear();
129         GetChild()->SetRefereeState(RefereeState::SUCCEED);
130         for (const auto& touchId : touchIds) {
131             GetChild()->OnAccepted(touchId);
132         }
133 
134         state_ = DetectState::DETECTED;
135         Adjudicate(AceType::Claim(this), GestureDisposal::ACCEPT);
136     } else if (disposal == GestureDisposal::REJECT) {
137         touchIds_.clear();
138         start_.reset();
139 
140         GetChild()->SetRefereeState(RefereeState::FAIL);
141         for (const auto& touchId : touchIds) {
142             GetChild()->OnRejected(touchId);
143         }
144 
145         state_ = DetectState::READY;
146         GetChild()->SetRefereeState(RefereeState::DETECTING);
147 
148         Adjudicate(AceType::Claim(this), GestureDisposal::REJECT);
149     } else if (disposal == GestureDisposal::PENDING) {
150         touchIds_.clear();
151         start_.reset();
152 
153         GetChild()->SetRefereeState(RefereeState::PENDING);
154         Adjudicate(AceType::Claim(this), GestureDisposal::PENDING);
155     }
156 }
157 
HandleTouchDownEvent(const TouchEvent & event)158 void TimeoutRecognizer::HandleTouchDownEvent(const TouchEvent& event)
159 {
160     if (!start_) {
161         start_ = event.time;
162         touchIds_.insert(event.id);
163         GetChild()->HandleEvent(event);
164         return;
165     }
166 
167     if (!CheckTimeout(event.time)) {
168         return;
169     }
170 }
171 
HandleTouchUpEvent(const TouchEvent & event)172 void TimeoutRecognizer::HandleTouchUpEvent(const TouchEvent& event)
173 {
174     if (!CheckTimeout(event.time)) {
175         return;
176     }
177 
178     GetChild()->HandleEvent(event);
179 }
180 
HandleTouchMoveEvent(const TouchEvent & event)181 void TimeoutRecognizer::HandleTouchMoveEvent(const TouchEvent& event)
182 {
183     if (!CheckTimeout(event.time)) {
184         return;
185     }
186 
187     GetChild()->HandleEvent(event);
188 }
189 
HandleTouchCancelEvent(const TouchEvent & event)190 void TimeoutRecognizer::HandleTouchCancelEvent(const TouchEvent& event)
191 {
192     if (!CheckTimeout(event.time)) {
193         return;
194     }
195 
196     GetChild()->HandleEvent(event);
197 }
198 
HandleTouchDownEvent(const AxisEvent & event)199 void TimeoutRecognizer::HandleTouchDownEvent(const AxisEvent& event)
200 {
201     if (!start_) {
202         start_ = event.time;
203         touchIds_.insert(0);
204         GetChild()->HandleEvent(event);
205         return;
206     }
207 
208     if (!CheckTimeout(event.time)) {
209         return;
210     }
211 }
212 
HandleTouchUpEvent(const AxisEvent & event)213 void TimeoutRecognizer::HandleTouchUpEvent(const AxisEvent& event)
214 {
215     if (!CheckTimeout(event.time)) {
216         return;
217     }
218 
219     GetChild()->HandleEvent(event);
220 }
221 
HandleTouchMoveEvent(const AxisEvent & event)222 void TimeoutRecognizer::HandleTouchMoveEvent(const AxisEvent& event)
223 {
224     if (!CheckTimeout(event.time)) {
225         return;
226     }
227 
228     GetChild()->HandleEvent(event);
229 }
230 
HandleTouchCancelEvent(const AxisEvent & event)231 void TimeoutRecognizer::HandleTouchCancelEvent(const AxisEvent& event)
232 {
233     if (!CheckTimeout(event.time)) {
234         return;
235     }
236 
237     GetChild()->HandleEvent(event);
238 }
239 
CheckTimeout(TimeStamp time)240 bool TimeoutRecognizer::CheckTimeout(TimeStamp time)
241 {
242     if (start_ && time > (*start_ + timeout_)) {
243         start_.reset();
244 
245         std::set<size_t> ids;
246         std::swap(ids, touchIds_);
247         GetChild()->SetRefereeState(RefereeState::FAIL);
248         for (auto const& touchId : touchIds_) {
249             GetChild()->OnRejected(touchId);
250         }
251 
252         state_ = DetectState::READY;
253         GetChild()->SetRefereeState(RefereeState::DETECTING);
254 
255         BatchAdjudicate(ids, GetChild(), GestureDisposal::REJECT);
256 
257         return false;
258     }
259 
260     return true;
261 }
262 } // namespace OHOS::Ace
263