1 /* 2 * Copyright (c) 2021-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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_EVENT_TOUCH_EVENT_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_EVENT_TOUCH_EVENT_H 18 19 #include <list> 20 21 #include "base/geometry/offset.h" 22 #include "base/memory/ace_type.h" 23 #include "core/event/ace_events.h" 24 #include "core/event/axis_event.h" 25 26 namespace OHOS::MMI { 27 class PointerEvent; 28 } // namespace OHOS::MMI 29 30 namespace OHOS::Ace { 31 32 static const int32_t TOUCH_TOOL_BASE_ID = 100; 33 34 enum class TouchType : size_t { 35 DOWN = 0, 36 UP, 37 MOVE, 38 CANCEL, 39 PULL_DOWN, 40 PULL_UP, 41 PULL_MOVE, 42 PULL_IN_WINDOW, 43 PULL_OUT_WINDOW, 44 UNKNOWN, 45 }; 46 47 struct TouchPoint final { 48 int32_t id = 0; 49 float x = 0.0f; 50 float y = 0.0f; 51 float screenX = 0.0f; 52 float screenY = 0.0f; 53 TimeStamp downTime; 54 double size = 0.0; 55 float force = 0.0f; 56 std::optional<float> tiltX; 57 std::optional<float> tiltY; 58 SourceTool sourceTool = SourceTool::UNKNOWN; 59 bool isPressed = false; 60 }; 61 62 /** 63 * @brief TouchEvent contains the active change point and a list of all touch points. 64 */ 65 struct TouchEvent final { 66 // the active changed point info 67 // The ID is used to identify the point of contact between the finger and the screen. Different fingers have 68 // different ids. 69 int32_t id = 0; 70 float x = 0.0f; 71 float y = 0.0f; 72 float screenX = 0.0f; 73 float screenY = 0.0f; 74 TouchType type = TouchType::UNKNOWN; 75 TouchType pullType = TouchType::UNKNOWN; 76 // nanosecond time stamp. 77 TimeStamp time; 78 double size = 0.0; 79 float force = 0.0f; 80 std::optional<float> tiltX; 81 std::optional<float> tiltY; 82 int64_t deviceId = 0; 83 int32_t targetDisplayId = 0; 84 SourceType sourceType = SourceType::NONE; 85 SourceTool sourceTool = SourceTool::UNKNOWN; 86 87 // all points on the touch screen. 88 std::vector<TouchPoint> pointers; 89 std::shared_ptr<MMI::PointerEvent> pointerEvent; 90 std::vector<uint8_t> enhanceData; 91 // historical points 92 std::vector<TouchEvent> history; 93 ToJsonValuefinal94 void ToJsonValue(std::unique_ptr<JsonValue>& json) const 95 { 96 json->Put("id", id); 97 json->Put("x", x); 98 json->Put("y", y); 99 json->Put("sx", screenX); 100 json->Put("sy", screenY); 101 json->Put("ty", static_cast<int32_t>(type)); 102 int64_t timeValue = std::chrono::duration_cast<std::chrono::nanoseconds>(time.time_since_epoch()).count(); 103 json->Put("ti", timeValue); 104 json->Put("si", size); 105 json->Put("f", force); 106 int32_t hasTiltX = tiltX.has_value() ? 1 : 0; 107 json->Put("hx", hasTiltX); 108 if (hasTiltX) { 109 json->Put("tx", tiltX.value()); 110 } 111 int32_t hasTiltY = tiltY.has_value() ? 1 : 0; 112 json->Put("hy", hasTiltY); 113 if (tiltY.has_value()) { 114 json->Put("ty", tiltY.value()); 115 } 116 json->Put("d", deviceId); 117 json->Put("sty", static_cast<int32_t>(sourceType)); 118 json->Put("sto", static_cast<int32_t>(sourceTool)); 119 } 120 FromJsonfinal121 void FromJson(const std::unique_ptr<JsonValue>& json) 122 { 123 id = json->GetInt("id"); 124 x = json->GetDouble("x"); 125 y = json->GetDouble("y"); 126 screenX = json->GetDouble("sx"); 127 screenY = json->GetDouble("sy"); 128 type = static_cast<TouchType>(json->GetInt("ty")); 129 int64_t timeValue = json->GetInt64("ti"); 130 time = TimeStamp(std::chrono::nanoseconds(timeValue)); 131 size = json->GetDouble("si"); 132 force = json->GetDouble("f"); 133 int32_t hasTiltX = json->GetInt("hx"); 134 int32_t hasTiltY = json->GetInt("hy"); 135 if (hasTiltX) { 136 tiltX = json->GetDouble("tx"); 137 } 138 if (hasTiltY) { 139 tiltY = json->GetDouble("ty"); 140 } 141 deviceId = json->GetInt64("d"); 142 sourceType = static_cast<SourceType>(json->GetInt("sty")); 143 sourceTool = static_cast<SourceTool>(json->GetInt("sto")); 144 } 145 GetOffsetfinal146 Offset GetOffset() const 147 { 148 return Offset(x, y); 149 } 150 GetScreenOffsetfinal151 Offset GetScreenOffset() const 152 { 153 return Offset(screenX, screenY); 154 } 155 CovertIdfinal156 void CovertId() 157 { 158 if ((sourceType == SourceType::TOUCH) && (sourceTool == SourceTool::PEN)) { 159 id = TOUCH_TOOL_BASE_ID + (int32_t)sourceTool; 160 } 161 } 162 CreateScalePointfinal163 TouchEvent CreateScalePoint(float scale) const 164 { 165 if (NearZero(scale)) { 166 return { id, x, y, screenX, screenY, type, pullType, time, size, force, tiltX, tiltY, deviceId, 167 targetDisplayId, sourceType, sourceTool, pointers, pointerEvent, enhanceData }; 168 } 169 auto temp = pointers; 170 std::for_each(temp.begin(), temp.end(), [scale](auto&& point) { 171 point.x = point.x / scale; 172 point.y = point.y / scale; 173 point.screenX = point.screenX / scale; 174 point.screenY = point.screenY / scale; 175 }); 176 return { id, x / scale, y / scale, screenX / scale, screenY / scale, type, pullType, time, size, force, tiltX, 177 tiltY, deviceId, targetDisplayId, sourceType, sourceTool, temp, pointerEvent, enhanceData }; 178 } 179 UpdateScalePointfinal180 TouchEvent UpdateScalePoint(float scale, float offsetX, float offsetY, int32_t pointId) const 181 { 182 auto temp = pointers; 183 if (NearZero(scale)) { 184 std::for_each(temp.begin(), temp.end(), [offsetX, offsetY](auto&& point) { 185 point.x = point.x - offsetX; 186 point.y = point.y - offsetY; 187 point.screenX = point.screenX - offsetX; 188 point.screenY = point.screenY - offsetY; 189 }); 190 return { pointId, x - offsetX, y - offsetY, screenX - offsetX, screenY - offsetY, type, pullType, time, 191 size, force, tiltX, tiltY, deviceId, targetDisplayId, sourceType, sourceTool, temp, pointerEvent, 192 enhanceData }; 193 } 194 195 std::for_each(temp.begin(), temp.end(), [scale, offsetX, offsetY](auto&& point) { 196 point.x = (point.x - offsetX) / scale; 197 point.y = (point.y - offsetY) / scale; 198 point.screenX = (point.screenX - offsetX) / scale; 199 point.screenY = (point.screenY - offsetY) / scale; 200 }); 201 return { pointId, (x - offsetX) / scale, (y - offsetY) / scale, (screenX - offsetX) / scale, 202 (screenY - offsetY) / scale, type, pullType, time, size, force, tiltX, tiltY, deviceId, targetDisplayId, 203 sourceType, sourceTool, temp, pointerEvent, enhanceData }; 204 } 205 UpdatePointersfinal206 TouchEvent UpdatePointers() const 207 { 208 TouchPoint point { .id = id, 209 .x = x, 210 .y = y, 211 .screenX = screenX, 212 .screenY = screenY, 213 .downTime = time, 214 .size = size, 215 .force = force, 216 .isPressed = (type == TouchType::DOWN) }; 217 TouchEvent event { .id = id, 218 .x = x, 219 .y = y, 220 .screenX = screenX, 221 .screenY = screenY, 222 .type = type, 223 .time = time, 224 .size = size, 225 .force = force, 226 .deviceId = deviceId, 227 .targetDisplayId = targetDisplayId, 228 .sourceType = sourceType, 229 .pointerEvent = pointerEvent, 230 .enhanceData = enhanceData }; 231 event.pointers.emplace_back(std::move(point)); 232 return event; 233 } 234 }; 235 236 struct TouchRestrict final { 237 static constexpr uint32_t NONE = 0x00000000; 238 static constexpr uint32_t CLICK = 0x00000001; 239 static constexpr uint32_t LONG_PRESS = 0x00000010; 240 static constexpr uint32_t SWIPE_LEFT = 0x00000100; 241 static constexpr uint32_t SWIPE_RIGHT = 0x00000200; 242 static constexpr uint32_t SWIPE_UP = 0x00000400; 243 static constexpr uint32_t SWIPE_DOWN = 0x00000800; 244 static constexpr uint32_t SWIPE = 0x00000F00; 245 static constexpr uint32_t SWIPE_VERTICAL = 0x0000C00; // Vertical 246 static constexpr uint32_t SWIPE_HORIZONTAL = 0x0000300; // Horizontal 247 static constexpr uint32_t TOUCH = 0xFFFFFFFF; 248 249 uint32_t forbiddenType = NONE; 250 UpdateForbiddenTypefinal251 void UpdateForbiddenType(uint32_t gestureType) 252 { 253 forbiddenType |= gestureType; 254 } 255 SourceType sourceType = SourceType::NONE; 256 257 SourceType hitTestType = SourceType::TOUCH; 258 259 TouchEvent touchEvent; 260 }; 261 262 class TouchCallBackInfo : public BaseEventInfo { 263 DECLARE_RELATIONSHIP_OF_CLASSES(TouchCallBackInfo, BaseEventInfo); 264 265 public: TouchCallBackInfo(TouchType type)266 explicit TouchCallBackInfo(TouchType type) : BaseEventInfo("onTouchEvent"), touchType_(type) {} 267 ~TouchCallBackInfo() override = default; 268 SetScreenX(float screenX)269 void SetScreenX(float screenX) 270 { 271 screenX_ = screenX; 272 } GetScreenX()273 float GetScreenX() const 274 { 275 return screenX_; 276 } SetScreenY(float screenY)277 void SetScreenY(float screenY) 278 { 279 screenY_ = screenY; 280 } GetScreenY()281 float GetScreenY() const 282 { 283 return screenY_; 284 } SetLocalX(float localX)285 void SetLocalX(float localX) 286 { 287 localX_ = localX; 288 } GetLocalX()289 float GetLocalX() const 290 { 291 return localX_; 292 } SetLocalY(float localY)293 void SetLocalY(float localY) 294 { 295 localY_ = localY; 296 } GetLocalY()297 float GetLocalY() const 298 { 299 return localY_; 300 } SetTouchType(TouchType type)301 void SetTouchType(TouchType type) 302 { 303 touchType_ = type; 304 } GetTouchType()305 TouchType GetTouchType() const 306 { 307 return touchType_; 308 } SetTimeStamp(const TimeStamp & time)309 void SetTimeStamp(const TimeStamp& time) 310 { 311 time_ = time; 312 } GetTimeStamp()313 TimeStamp GetTimeStamp() const 314 { 315 return time_; 316 } 317 318 private: 319 float screenX_ = 0.0f; 320 float screenY_ = 0.0f; 321 float localX_ = 0.0f; 322 float localY_ = 0.0f; 323 TouchType touchType_ = TouchType::UNKNOWN; 324 TimeStamp time_; 325 }; 326 327 class TouchLocationInfo : public BaseEventInfo { 328 DECLARE_RELATIONSHIP_OF_CLASSES(TouchLocationInfo, TypeInfoBase); 329 330 public: TouchLocationInfo(int32_t fingerId)331 explicit TouchLocationInfo(int32_t fingerId) : BaseEventInfo("default") 332 { 333 fingerId_ = fingerId; 334 } TouchLocationInfo(const std::string & type,int32_t fingerId)335 explicit TouchLocationInfo(const std::string& type, int32_t fingerId) : BaseEventInfo(type) 336 { 337 fingerId_ = fingerId; 338 } 339 ~TouchLocationInfo() override = default; 340 SetGlobalLocation(const Offset & globalLocation)341 TouchLocationInfo& SetGlobalLocation(const Offset& globalLocation) 342 { 343 globalLocation_ = globalLocation; 344 return *this; 345 } SetLocalLocation(const Offset & localLocation)346 TouchLocationInfo& SetLocalLocation(const Offset& localLocation) 347 { 348 localLocation_ = localLocation; 349 return *this; 350 } 351 SetScreenLocation(const Offset & screenLocation)352 TouchLocationInfo& SetScreenLocation(const Offset& screenLocation) 353 { 354 screenLocation_ = screenLocation; 355 return *this; 356 } 357 GetScreenLocation()358 const Offset& GetScreenLocation() const 359 { 360 return screenLocation_; 361 } 362 GetLocalLocation()363 const Offset& GetLocalLocation() const 364 { 365 return localLocation_; 366 } GetGlobalLocation()367 const Offset& GetGlobalLocation() const 368 { 369 return globalLocation_; 370 } GetFingerId()371 int32_t GetFingerId() const 372 { 373 return fingerId_; 374 } 375 SetSize(double size)376 void SetSize(double size) 377 { 378 size_ = size; 379 } 380 GetSize()381 double GetSize() const 382 { 383 return size_; 384 } 385 SetTouchDeviceId(int64_t deviceId)386 void SetTouchDeviceId(int64_t deviceId) 387 { 388 touchDeviceId_ = deviceId; 389 } 390 GetTouchDeviceId()391 int64_t GetTouchDeviceId() const 392 { 393 return touchDeviceId_; 394 } 395 GetTouchType()396 TouchType GetTouchType() const 397 { 398 return touchType_; 399 } SetTouchType(TouchType type)400 void SetTouchType(TouchType type) 401 { 402 touchType_ = type; 403 } 404 405 private: 406 // The finger id is used to identify the point of contact between the finger and the screen. Different fingers have 407 // different ids. 408 int32_t fingerId_ = -1; 409 410 // global position at which the touch point contacts the screen. 411 Offset globalLocation_; 412 // Different from global location, The local location refers to the location of the contact point relative to the 413 // current node which has the recognizer. 414 Offset localLocation_; 415 416 Offset screenLocation_; 417 418 // finger touch size 419 double size_ = 0.0; 420 421 // input device id 422 int64_t touchDeviceId_ = 0; 423 424 // touch type 425 TouchType touchType_ = TouchType::UNKNOWN; 426 }; 427 428 using GetEventTargetImpl = std::function<std::optional<EventTarget>()>; 429 430 class ACE_EXPORT TouchEventTarget : public virtual AceType { 431 DECLARE_ACE_TYPE(TouchEventTarget, AceType); 432 433 public: 434 TouchEventTarget() = default; TouchEventTarget(std::string nodeName,int32_t nodeId)435 TouchEventTarget(std::string nodeName, int32_t nodeId) : nodeName_(std::move(nodeName)), nodeId_(nodeId) {} 436 ~TouchEventTarget() override = default; 437 438 // if return false means need to stop event dispatch. 439 virtual bool DispatchEvent(const TouchEvent& point) = 0; 440 // if return false means need to stop event bubbling. 441 virtual bool HandleEvent(const TouchEvent& point) = 0; HandleEvent(const AxisEvent & event)442 virtual bool HandleEvent(const AxisEvent& event) 443 { 444 return true; 445 } OnFlushTouchEventsBegin()446 virtual void OnFlushTouchEventsBegin() {} OnFlushTouchEventsEnd()447 virtual void OnFlushTouchEventsEnd() {} 448 SetTouchRestrict(const TouchRestrict & touchRestrict)449 void SetTouchRestrict(const TouchRestrict& touchRestrict) 450 { 451 touchRestrict_ = touchRestrict; 452 } 453 SetGetEventTargetImpl(const GetEventTargetImpl & getEventTargetImpl)454 void SetGetEventTargetImpl(const GetEventTargetImpl& getEventTargetImpl) 455 { 456 getEventTargetImpl_ = getEventTargetImpl; 457 } 458 GetEventTarget()459 std::optional<EventTarget> GetEventTarget() const 460 { 461 if (getEventTargetImpl_) { 462 return getEventTargetImpl_(); 463 } 464 return std::nullopt; 465 } 466 467 // Coordinate offset is used to calculate the local location of the touch point in the render node. SetCoordinateOffset(const Offset & coordinateOffset)468 void SetCoordinateOffset(const Offset& coordinateOffset) 469 { 470 coordinateOffset_ = coordinateOffset; 471 } 472 473 // Gets the coordinate offset to calculate the local location of the touch point by manually. GetCoordinateOffset()474 const Offset& GetCoordinateOffset() const 475 { 476 return coordinateOffset_; 477 } 478 SetSubPipelineGlobalOffset(const Offset & subPipelineGlobalOffset,float viewScale)479 void SetSubPipelineGlobalOffset(const Offset& subPipelineGlobalOffset, float viewScale) 480 { 481 subPipelineGlobalOffset_ = subPipelineGlobalOffset; 482 viewScale_ = viewScale; 483 } 484 DispatchMultiContainerEvent(const TouchEvent & point)485 bool DispatchMultiContainerEvent(const TouchEvent& point) 486 { 487 #ifdef OHOS_STANDARD_SYSTEM 488 if (!subPipelineGlobalOffset_.IsZero()) { 489 auto multiContainerPoint = point.UpdateScalePoint( 490 viewScale_, subPipelineGlobalOffset_.GetX(), subPipelineGlobalOffset_.GetY(), point.id); 491 return DispatchEvent(multiContainerPoint); 492 } 493 #endif 494 return DispatchEvent(point); 495 } 496 HandleMultiContainerEvent(const TouchEvent & point)497 bool HandleMultiContainerEvent(const TouchEvent& point) 498 { 499 #ifdef OHOS_STANDARD_SYSTEM 500 if (!subPipelineGlobalOffset_.IsZero()) { 501 auto multiContainerPoint = point.UpdateScalePoint( 502 viewScale_, subPipelineGlobalOffset_.GetX(), subPipelineGlobalOffset_.GetY(), point.id); 503 return HandleEvent(multiContainerPoint); 504 } 505 #endif 506 return HandleEvent(point); 507 } 508 GetNodeName()509 std::string GetNodeName() const 510 { 511 return nodeName_; 512 } 513 GetNodeId()514 int32_t GetNodeId() const 515 { 516 return nodeId_; 517 } 518 519 protected: 520 Offset coordinateOffset_; 521 GetEventTargetImpl getEventTargetImpl_; 522 TouchRestrict touchRestrict_ { TouchRestrict::NONE }; 523 Offset subPipelineGlobalOffset_; 524 float viewScale_ = 1.0f; 525 std::string nodeName_ = "NULL"; 526 int32_t nodeId_ = -1; 527 }; 528 529 using TouchTestResult = std::list<RefPtr<TouchEventTarget>>; 530 531 class TouchEventInfo : public BaseEventInfo { 532 DECLARE_RELATIONSHIP_OF_CLASSES(TouchEventInfo, BaseEventInfo); 533 534 public: TouchEventInfo(const std::string & type)535 explicit TouchEventInfo(const std::string& type) : BaseEventInfo(type) {} 536 ~TouchEventInfo() override = default; 537 AddTouchLocationInfo(TouchLocationInfo && info)538 void AddTouchLocationInfo(TouchLocationInfo&& info) 539 { 540 touches_.emplace_back(info); 541 } AddChangedTouchLocationInfo(TouchLocationInfo && info)542 void AddChangedTouchLocationInfo(TouchLocationInfo&& info) 543 { 544 changedTouches_.emplace_back(info); 545 } AddHistoryLocationInfo(TouchLocationInfo && info)546 void AddHistoryLocationInfo(TouchLocationInfo&& info) 547 { 548 history_.emplace_back(std::move(info)); 549 } 550 GetTouches()551 const std::list<TouchLocationInfo>& GetTouches() const 552 { 553 return touches_; 554 } GetChangedTouches()555 const std::list<TouchLocationInfo>& GetChangedTouches() const 556 { 557 return changedTouches_; 558 } GetHistory()559 const std::list<TouchLocationInfo>& GetHistory() const 560 { 561 return history_; 562 } 563 SetPointerEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent)564 void SetPointerEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent) 565 { 566 pointerEvent_ = pointerEvent; 567 } GetPointerEvent()568 const std::shared_ptr<MMI::PointerEvent> GetPointerEvent() const 569 { 570 return pointerEvent_; 571 } 572 573 private: 574 std::shared_ptr<MMI::PointerEvent> pointerEvent_; 575 std::list<TouchLocationInfo> touches_; 576 std::list<TouchLocationInfo> changedTouches_; 577 std::list<TouchLocationInfo> history_; 578 }; 579 580 using TouchEventFunc = std::function<void(TouchEventInfo&)>; 581 using OnTouchEventCallback = std::function<void(const TouchEventInfo&)>; 582 using CatchTouchEventCallback = std::function<void()>; 583 584 } // namespace OHOS::Ace 585 586 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_EVENT_TOUCH_EVENT_H 587