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