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 30namespace OHOS { 31void 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 59void 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 103bool 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 155void 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 183void 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 215void 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 235void 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 263void 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 295void 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 311void 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 328void 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