1 /*
2 * Copyright (c) 2020-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 "dock/pointer_input_device.h"
17
18 #include "components/root_view.h"
19 #include "components/ui_tree_manager.h"
20 #include "core/render_manager.h"
21 #if ENABLE_AOD
22 #include "events/aod_callback.h"
23 #endif
24 #include "gfx_utils/graphic_log.h"
25 #include "gfx_utils/graphic_math.h"
26 #if ENABLE_WINDOW
27 #include "window/window.h"
28 #endif
29
30 namespace OHOS {
DispatchEvent(const DeviceData & data)31 void PointerInputDevice::DispatchEvent(const DeviceData& data)
32 {
33 curPos_ = data.point;
34 #if ENABLE_WINDOW
35 Window* window = RenderManager::GetInstance().GetWindowById(data.winId);
36 if (window == nullptr) {
37 return;
38 }
39 curPos_.x = curPos_.x - window->GetRect().GetLeft();
40 curPos_.y = curPos_.y - window->GetRect().GetTop();
41 UIViewGroup* rootView = window->GetRootView();
42 #else
43 UIViewGroup* rootView = RootView::GetInstance();
44 #endif
45 if (rootView == nullptr) {
46 GRAPHIC_LOGE("No valid rootview to dispatch input event!\n");
47 return;
48 }
49
50 if (data.state == STATE_PRESS) {
51 DispatchPressEvent(rootView);
52 } else {
53 DispatchReleaseEvent(rootView);
54 }
55 dragLastPos_ = lastPos_;
56 lastPos_ = curPos_;
57 }
58
DispatchPressEvent(UIViewGroup * rootView)59 void PointerInputDevice::DispatchPressEvent(UIViewGroup* rootView)
60 {
61 // first time to press
62 if (!pressState_) {
63 rootView->GetTargetView(curPos_, &touchableView_, &targetView_);
64 if (touchableView_ == nullptr) {
65 GRAPHIC_LOGD("PointerInputDevice::DispatchPressEvent cannot find target view!\n");
66 return;
67 }
68 draggableView_ = GetDraggableView(touchableView_);
69 pressState_ = true;
70 pressTimeStamp_ = HALTick::GetInstance().GetTime();
71 lastPos_ = curPos_;
72 dragLastPos_ = lastPos_;
73 return;
74 }
75 uint32_t elapse = HALTick::GetInstance().GetElapseTime(pressTimeStamp_);
76 DispatchDragStartEvent();
77 DispatchDragEvent();
78 if (!isDragging_ && (touchableView_ != nullptr) && !cancelSent_) {
79 UIView* tempView = nullptr;
80 rootView->GetTargetView(curPos_, &tempView, &targetView_);
81 if (tempView != touchableView_) {
82 DispatchCancelEvent();
83 } else {
84 if (!pressSent_ && (elapse > INDEV_PRESS_TIME_IN_DRAG)) {
85 PressEvent evt(curPos_);
86 UIView* parent = touchableView_->GetParent();
87 if (!touchableView_->OnPressEvent(evt)) {
88 while (parent != nullptr) {
89 PressEvent evtParent(curPos_);
90 if (parent->OnPressEvent(evtParent)) {
91 break;
92 }
93 parent = parent->GetParent();
94 }
95 }
96 pressSent_ = true;
97 }
98 DispatchLongPressEvent(elapse);
99 }
100 }
101 }
102
ProcessReleaseEvent()103 bool PointerInputDevice::ProcessReleaseEvent()
104 {
105 UIView* parent = touchableView_->GetParent();
106 // reissue press event.
107 if (!pressSent_) {
108 PressEvent evtPress(curPos_);
109 if (!touchableView_->OnPressEvent(evtPress)) {
110 while (parent != nullptr) {
111 PressEvent evtPressParent(curPos_);
112 if (parent->OnPressEvent(evtPressParent)) {
113 break;
114 }
115 parent = parent->GetParent();
116 }
117 }
118 pressSent_ = true;
119 return false;
120 } else {
121 ReleaseEvent evtRelease(curPos_);
122 if (!touchableView_->OnReleaseEvent(evtRelease)) {
123 while (parent != nullptr) {
124 ReleaseEvent evtReleaseParent(curPos_);
125 if (parent->OnReleaseEvent(evtReleaseParent)) {
126 break;
127 }
128 parent = parent->GetParent();
129 }
130 }
131
132 if (pressSent_ && needClick_) {
133 ClickEvent evt(curPos_);
134 parent = touchableView_->GetParent();
135 if (!touchableView_->OnClickEvent(evt)) {
136 while (parent != nullptr) {
137 #if ENABLE_AOD
138 OnClickEventHappen(parent);
139 #endif
140 ClickEvent evtParent(curPos_);
141 if (parent->OnClickEvent(evtParent)) {
142 break;
143 }
144 parent = parent->GetParent();
145 }
146 }
147 #if ENABLE_AOD
148 OnClickEventHappen(*touchableView_);
149 #endif
150 }
151 }
152 return true;
153 }
154
DispatchReleaseEvent(UIViewGroup * rootView)155 void PointerInputDevice::DispatchReleaseEvent(UIViewGroup* rootView)
156 {
157 if (!pressState_) {
158 return;
159 }
160
161 DispatchDragStartEvent();
162 DispatchDragEndEvent();
163 if (!isDragging_ && (touchableView_ != nullptr) && !cancelSent_) {
164 UIView* tempView = nullptr;
165 rootView->GetTargetView(curPos_, &tempView, &targetView_);
166 if (tempView != touchableView_) {
167 DispatchCancelEvent();
168 } else {
169 if (!ProcessReleaseEvent()) {
170 return;
171 }
172 }
173 }
174 isDragging_ = false;
175 pressState_ = false;
176 pressSent_ = false;
177 cancelSent_ = false;
178 longPressSent_ = false;
179 needClick_ = true;
180 touchableView_ = nullptr;
181 }
182
DispatchDragStartEvent()183 void PointerInputDevice::DispatchDragStartEvent()
184 {
185 if (draggableView_ == nullptr) {
186 return;
187 }
188 dragStep_.x = curPos_.x - lastPos_.x;
189 dragStep_.y = curPos_.y - lastPos_.y;
190 dragLen_.x += dragStep_.x;
191 dragLen_.y += dragStep_.y;
192 if (!isDragging_) {
193 if ((MATH_ABS(dragLen_.x) >= INDEV_DRAG_LIMIT) || (MATH_ABS(dragLen_.y) >= INDEV_DRAG_LIMIT)) {
194 if ((touchableView_ != nullptr) && !cancelSent_) {
195 DispatchCancelEvent();
196 }
197 // Send Drag Begin Event.
198 DragEvent evt(curPos_, lastPos_, dragLen_);
199 UIView* parent = draggableView_->GetParent();
200 if (!draggableView_->OnDragStartEvent(evt)) {
201 while (parent != nullptr) {
202 DragEvent evtParent(curPos_, lastPos_, dragLen_);
203 if (parent->OnDragStartEvent(evtParent)) {
204 break;
205 }
206 parent = parent->GetParent();
207 }
208 }
209 dragLastPos_ = lastPos_;
210 isDragging_ = true;
211 }
212 }
213 }
214
DispatchDragEvent()215 void PointerInputDevice::DispatchDragEvent()
216 {
217 if ((draggableView_ == nullptr) || !isDragging_) {
218 return;
219 }
220 if ((dragStep_.x != 0) || (dragStep_.y != 0)) {
221 DragEvent evt(curPos_, lastPos_, dragLen_);
222 UIView* parent = draggableView_->GetParent();
223 if (!draggableView_->OnDragEvent(evt)) {
224 while (parent != nullptr) {
225 DragEvent evtParent(curPos_, lastPos_, dragLen_);
226 if (parent->OnDragEvent(evtParent)) {
227 break;
228 }
229 parent = parent->GetParent();
230 }
231 }
232 }
233 }
234
DispatchDragEndEvent()235 void PointerInputDevice::DispatchDragEndEvent()
236 {
237 if (draggableView_ == nullptr) {
238 return;
239 }
240
241 if (isDragging_) {
242 DragEvent evt(curPos_, lastPos_, dragLen_);
243 UIView* parent = draggableView_->GetParent();
244 evt.SetPreLastPoint(dragLastPos_);
245 if (!draggableView_->OnDragEndEvent(evt)) {
246 while (parent != nullptr) {
247 DragEvent evtParent(curPos_, lastPos_, dragLen_);
248 if (parent->OnDragEndEvent(evtParent)) {
249 break;
250 }
251 parent = parent->GetParent();
252 }
253 }
254 #if ENABLE_AOD
255 OnDragEndEventHappen(*draggableView_);
256 #endif
257 }
258 dragLen_ = {0, 0};
259 dragStep_ = {0, 0};
260 draggableView_ = nullptr;
261 }
262
DispatchLongPressEvent(uint32_t elapse)263 void PointerInputDevice::DispatchLongPressEvent(uint32_t elapse)
264 {
265 if (!longPressSent_ && (elapse > INDEV_LONG_PRESS_TIME)) {
266 longPressSent_ = true;
267 LongPressEvent evt(curPos_, pressTimeStamp_);
268 bool isConsumed = touchableView_->OnLongPressEvent(evt);
269 if (touchableView_->GetOnLongPressListener() != nullptr) {
270 needClick_ = false;
271 }
272 UIView* parent = touchableView_->GetParent();
273 #if ENABLE_AOD
274 OnLongPressEventHappen(*touchableView_);
275 #endif
276 if (!isConsumed) {
277 while (parent != nullptr) {
278 LongPressEvent evtParent(curPos_, pressTimeStamp_);
279 isConsumed = parent->OnLongPressEvent(evtParent);
280 if (needClick_ && (parent->GetOnLongPressListener() != nullptr)) {
281 needClick_ = false;
282 }
283 #if ENABLE_AOD
284 OnLongPressEventHappen(*parent);
285 #endif
286 if (isConsumed) {
287 break;
288 }
289 parent = parent->GetParent();
290 }
291 }
292 }
293 }
294
DispatchCancelEvent()295 void PointerInputDevice::DispatchCancelEvent()
296 {
297 CancelEvent evt(lastPos_);
298 UIView* parent = touchableView_->GetParent();
299 if (!touchableView_->OnCancelEvent(evt)) {
300 while (parent != nullptr) {
301 CancelEvent evtParent(lastPos_);
302 if (parent->OnCancelEvent(evtParent)) {
303 break;
304 }
305 parent = parent->GetParent();
306 }
307 }
308 cancelSent_ = true;
309 }
310
UpdateEventViews(UIView * view)311 void PointerInputDevice::UpdateEventViews(UIView* view)
312 {
313 // view should not be nullptr
314 // invalid touchable and draggable view will be reset to nullptr
315 if ((touchableView_ != nullptr) && RootView::FindSubView(*view, touchableView_)) {
316 touchableView_ = nullptr;
317 }
318
319 if ((draggableView_ != nullptr) && RootView::FindSubView(*view, draggableView_)) {
320 draggableView_ = nullptr;
321 dragLastPos_ = curPos_;
322 dragLen_ = {0, 0};
323 dragStep_ = {0, 0};
324 isDragging_ = false;
325 }
326 }
327
OnViewLifeEvent()328 void PointerInputDevice::OnViewLifeEvent()
329 {
330 UIView* view;
331 UITreeManager::ViewLifeEvent event;
332 UITreeManager::GetInstance().GetLastEvent(view, event);
333
334 if ((event != UITreeManager::REMOVE) || (view == nullptr)) {
335 return;
336 }
337 UpdateEventViews(view);
338 }
339
340 } // namespace OHOS
341