1 /* 2 * Copyright (c) 2021-2023 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_MOUSE_EVENT_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_EVENT_MOUSE_EVENT_H 18 19 #include <vector> 20 #include "base/geometry/ng/offset_t.h" 21 #include "base/geometry/offset.h" 22 #include "base/mousestyle/mouse_style.h" 23 #include "core/event/key_event.h" 24 #include "core/event/touch_event.h" 25 #include "core/pipeline_ng/ui_task_scheduler.h" 26 27 namespace OHOS::MMI { 28 class PointerEvent; 29 } // namespace OHOS::MMI 30 31 namespace OHOS::Ace { 32 33 class MouseInfo; 34 constexpr int32_t MOUSE_PRESS_LEFT = 1; 35 static const int32_t MOUSE_BASE_ID = 1000; 36 37 using OnMouseEventFunc = std::function<void(MouseInfo& info)>; 38 39 enum class MouseAction : int32_t { 40 NONE = 0, 41 PRESS = 1, 42 RELEASE = 2, 43 MOVE = 3, 44 WINDOW_ENTER = 4, 45 WINDOW_LEAVE = 5, 46 HOVER, 47 HOVER_ENTER, 48 HOVER_MOVE, 49 HOVER_EXIT, 50 PULL_DOWN, 51 PULL_MOVE, 52 PULL_UP, 53 CANCEL 54 }; 55 56 enum class AccessibilityHoverAction : int32_t { 57 UNKNOWN = -1, 58 HOVER_ENTER, 59 HOVER_MOVE, 60 HOVER_EXIT, 61 HOVER_CANCEL 62 }; 63 64 enum class MouseState : int32_t { 65 NONE = 0, 66 HOVER = 1, 67 }; 68 69 enum class MouseButton : int32_t { 70 NONE_BUTTON = 0, 71 LEFT_BUTTON = 1, 72 RIGHT_BUTTON = 2, 73 MIDDLE_BUTTON = 4, 74 BACK_BUTTON = 8, 75 FORWARD_BUTTON = 16, 76 SIDE_BUTTON = 32, 77 EXTRA_BUTTON = 64, 78 TASK_BUTTON = 128, 79 }; 80 81 enum class HoverEffectType : int32_t { 82 NONE, 83 OPACITY, 84 SCALE, 85 BOARD, 86 AUTO, 87 UNKNOWN, 88 }; 89 90 struct MouseEvent final : public PointerEvent { 91 int32_t id = 0; 92 float z = 0.0f; 93 float deltaX = 0.0f; 94 float deltaY = 0.0f; 95 float deltaZ = 0.0f; 96 float scrollX = 0.0f; 97 float scrollY = 0.0f; 98 float scrollZ = 0.0f; 99 float rawDeltaX = 0.0f; 100 float rawDeltaY = 0.0f; 101 std::vector<MouseButton> pressedButtonsArray; 102 MouseAction action = MouseAction::NONE; 103 MouseAction pullAction = MouseAction::NONE; 104 MouseButton button = MouseButton::NONE_BUTTON; 105 int32_t pressedButtons = 0; // combined by MouseButtons 106 int64_t deviceId = 0; 107 int32_t targetDisplayId = 0; 108 SourceType sourceType = SourceType::NONE; 109 SourceTool sourceTool = SourceTool::UNKNOWN; 110 std::shared_ptr<MMI::PointerEvent> pointerEvent; 111 int32_t touchEventId = 0; 112 int32_t originalId = 0; 113 std::vector<KeyCode> pressedKeyCodes_; 114 bool isInjected = false; 115 bool isPrivacyMode = false; 116 GetOffsetfinal117 Offset GetOffset() const 118 { 119 return Offset(x, y); 120 } 121 GetScreenOffsetfinal122 Offset GetScreenOffset() const 123 { 124 return Offset(screenX, screenY); 125 } 126 GetIdfinal127 int32_t GetId() const 128 { 129 if (pressedButtons > 0) { 130 return pressedButtons + MOUSE_BASE_ID; 131 } else { 132 return (int32_t)button + MOUSE_BASE_ID; 133 } 134 } 135 GetPointerIdfinal136 int32_t GetPointerId(int32_t pointerId) const 137 { 138 if (pressedButtons > 0) { 139 return pressedButtons + MOUSE_BASE_ID + pointerId; 140 } 141 return static_cast<int32_t>(button) + MOUSE_BASE_ID + pointerId; 142 } 143 CloneWithfinal144 MouseEvent CloneWith(float scale) const 145 { 146 if (NearEqual(scale, 0.f)) { 147 return {}; 148 } 149 MouseEvent mouseEvent; 150 mouseEvent.id = id; 151 mouseEvent.x = x / scale; 152 mouseEvent.y = y / scale; 153 mouseEvent.z = z / scale; 154 mouseEvent.deltaX = deltaX / scale; 155 mouseEvent.deltaY = deltaY / scale; 156 mouseEvent.deltaZ = deltaZ / scale; 157 mouseEvent.scrollX = scrollX / scale; 158 mouseEvent.scrollY = scrollY / scale; 159 mouseEvent.scrollZ = scrollZ / scale; 160 mouseEvent.screenX = screenX / scale; 161 mouseEvent.screenY = screenY / scale; 162 mouseEvent.action = action; 163 mouseEvent.pullAction = pullAction; 164 mouseEvent.button = button; 165 mouseEvent.pressedButtons = pressedButtons; 166 mouseEvent.time = time; 167 mouseEvent.deviceId = deviceId; 168 mouseEvent.targetDisplayId = targetDisplayId; 169 mouseEvent.sourceType = sourceType; 170 mouseEvent.sourceTool = sourceTool; 171 mouseEvent.pointerEvent = pointerEvent; 172 mouseEvent.originalId = originalId; 173 mouseEvent.pressedKeyCodes_ = pressedKeyCodes_; 174 mouseEvent.isInjected = isInjected; 175 mouseEvent.isPrivacyMode = isPrivacyMode; 176 mouseEvent.rawDeltaX = rawDeltaX; 177 mouseEvent.rawDeltaY = rawDeltaY; 178 mouseEvent.pressedButtonsArray = pressedButtonsArray; 179 return mouseEvent; 180 } 181 CreateScaleEventfinal182 MouseEvent CreateScaleEvent(float scale) const 183 { 184 if (NearZero(scale)) { 185 return CloneWith(1); 186 } 187 return CloneWith(scale); 188 } 189 CreateTouchPointfinal190 TouchEvent CreateTouchPoint() const 191 { 192 TouchType type = TouchType::UNKNOWN; 193 if (action == MouseAction::PRESS) { 194 type = TouchType::DOWN; 195 } else if (action == MouseAction::RELEASE) { 196 type = TouchType::UP; 197 } else if (action == MouseAction::MOVE) { 198 type = TouchType::MOVE; 199 } else if (action == MouseAction::CANCEL) { 200 type = TouchType::CANCEL; 201 } else { 202 type = TouchType::UNKNOWN; 203 } 204 int32_t pointId = id; 205 if (sourceType == SourceType::MOUSE) { 206 pointId = GetPointerId(pointId); 207 } 208 auto pointOriginalId = sourceType == SourceType::MOUSE ? GetId() : originalId; 209 TouchPoint point { .id = pointId, 210 .x = x, 211 .y = y, 212 .screenX = screenX, 213 .screenY = screenY, 214 .downTime = time, 215 .size = 0.0, 216 .isPressed = (type == TouchType::DOWN), 217 .originalId = pointOriginalId }; 218 TouchEvent event; 219 event.SetId(pointId) 220 .SetX(x) 221 .SetY(y) 222 .SetScreenX(screenX) 223 .SetScreenY(screenY) 224 .SetType(type) 225 .SetTime(time) 226 .SetSize(0.0) 227 .SetDeviceId(deviceId) 228 .SetTargetDisplayId(targetDisplayId) 229 .SetSourceType(sourceType) 230 .SetSourceTool(sourceTool) 231 .SetPointerEvent(pointerEvent) 232 .SetTouchEventId(touchEventId) 233 .SetOriginalId(pointOriginalId) 234 .SetIsInjected(isInjected); 235 event.isPrivacyMode = isPrivacyMode; 236 event.pointers.emplace_back(std::move(point)); 237 event.pressedKeyCodes_ = pressedKeyCodes_; 238 return event; 239 } 240 241 MouseEvent operator-(const Offset& offset) const; 242 }; 243 244 class MouseInfo : public BaseEventInfo { 245 DECLARE_RELATIONSHIP_OF_CLASSES(MouseInfo, BaseEventInfo); 246 247 public: MouseInfo()248 MouseInfo() : BaseEventInfo("onMouse") {} 249 ~MouseInfo() override = default; 250 SetButton(MouseButton button)251 void SetButton(MouseButton button) 252 { 253 button_ = button; 254 } 255 GetButton()256 MouseButton GetButton() const 257 { 258 return button_; 259 } 260 SetAction(MouseAction action)261 void SetAction(MouseAction action) 262 { 263 action_ = action; 264 } 265 GetAction()266 MouseAction GetAction() const 267 { 268 return action_; 269 } 270 SetPullAction(MouseAction pullAction)271 void SetPullAction(MouseAction pullAction) 272 { 273 pullAction_ = pullAction; 274 } 275 GetPullAction()276 MouseAction GetPullAction() const 277 { 278 return pullAction_; 279 } 280 SetGlobalLocation(const Offset & globalLocation)281 MouseInfo& SetGlobalLocation(const Offset& globalLocation) 282 { 283 globalLocation_ = globalLocation; 284 return *this; 285 } SetLocalLocation(const Offset & localLocation)286 MouseInfo& SetLocalLocation(const Offset& localLocation) 287 { 288 localLocation_ = localLocation; 289 return *this; 290 } 291 SetScreenLocation(const Offset & screenLocation)292 MouseInfo& SetScreenLocation(const Offset& screenLocation) 293 { 294 screenLocation_ = screenLocation; 295 return *this; 296 } 297 GetScreenLocation()298 const Offset& GetScreenLocation() const 299 { 300 return screenLocation_; 301 } 302 GetLocalLocation()303 const Offset& GetLocalLocation() const 304 { 305 return localLocation_; 306 } GetGlobalLocation()307 const Offset& GetGlobalLocation() const 308 { 309 return globalLocation_; 310 } 311 SetPointerEvent(const std::shared_ptr<MMI::PointerEvent> & pointerEvent)312 void SetPointerEvent(const std::shared_ptr<MMI::PointerEvent>& pointerEvent) 313 { 314 pointerEvent_ = pointerEvent; 315 } GetPointerEvent()316 const std::shared_ptr<MMI::PointerEvent> GetPointerEvent() const 317 { 318 return pointerEvent_; 319 } 320 SetRawDeltaX(float rawDeltaX)321 void SetRawDeltaX(float rawDeltaX) 322 { 323 rawDeltaX_ = rawDeltaX; 324 } GetRawDeltaX()325 float GetRawDeltaX() 326 { 327 return rawDeltaX_; 328 } 329 SetRawDeltaY(float rawDeltaY)330 void SetRawDeltaY(float rawDeltaY) 331 { 332 rawDeltaY_ = rawDeltaY; 333 } GetRawDeltaY()334 float GetRawDeltaY() 335 { 336 return rawDeltaY_; 337 } 338 SetPressedButtons(const std::vector<MouseButton> & pressedButtonsArray)339 void SetPressedButtons(const std::vector<MouseButton>& pressedButtonsArray) 340 { 341 pressedButtonsArray_ = pressedButtonsArray; 342 } GetPressedButtons()343 std::vector<MouseButton> GetPressedButtons() 344 { 345 return pressedButtonsArray_; 346 } 347 348 private: 349 std::shared_ptr<MMI::PointerEvent> pointerEvent_; 350 MouseButton button_ = MouseButton::NONE_BUTTON; 351 MouseAction action_ = MouseAction::NONE; 352 MouseAction pullAction_ = MouseAction::NONE; 353 // global position at which the touch point contacts the screen. 354 Offset globalLocation_; 355 // Different from global location, The local location refers to the location of the contact point relative to the 356 // current node which has the recognizer. 357 Offset localLocation_; 358 Offset screenLocation_; 359 float rawDeltaX_ = 0.0f; 360 float rawDeltaY_ = 0.0f; 361 std::vector<MouseButton> pressedButtonsArray_; 362 }; 363 364 using HoverEffectFunc = std::function<void(bool)>; 365 366 class HoverInfo; 367 class HoverInfo : public BaseEventInfo { 368 DECLARE_RELATIONSHIP_OF_CLASSES(HoverInfo, BaseEventInfo); 369 370 public: HoverInfo()371 HoverInfo() : BaseEventInfo("onHover") {} 372 ~HoverInfo() override = default; 373 SetGlobalLocation(const Offset & globalLocation)374 HoverInfo& SetGlobalLocation(const Offset& globalLocation) 375 { 376 globalLocation_ = globalLocation; 377 return *this; 378 } SetLocalLocation(const Offset & localLocation)379 HoverInfo& SetLocalLocation(const Offset& localLocation) 380 { 381 localLocation_ = localLocation; 382 return *this; 383 } 384 SetScreenLocation(const Offset & screenLocation)385 HoverInfo& SetScreenLocation(const Offset& screenLocation) 386 { 387 screenLocation_ = screenLocation; 388 return *this; 389 } 390 GetScreenLocation()391 const Offset& GetScreenLocation() const 392 { 393 return screenLocation_; 394 } 395 GetLocalLocation()396 const Offset& GetLocalLocation() const 397 { 398 return localLocation_; 399 } 400 GetGlobalLocation()401 const Offset& GetGlobalLocation() const 402 { 403 return globalLocation_; 404 } 405 406 private: 407 // global position at which the touch point contacts the screen. 408 Offset globalLocation_; 409 // Different from global location, The local location refers to the location of the contact point relative to the 410 // current node which has the recognizer. 411 Offset localLocation_; 412 413 Offset screenLocation_; 414 }; 415 416 class AccessibilityHoverInfo : public BaseEventInfo { 417 DECLARE_RELATIONSHIP_OF_CLASSES(AccessibilityHoverInfo, BaseEventInfo); 418 419 public: AccessibilityHoverInfo()420 AccessibilityHoverInfo() : BaseEventInfo("onAccessibilityHover") {} 421 ~AccessibilityHoverInfo() override = default; 422 SetGlobalLocation(const Offset & globalLocation)423 AccessibilityHoverInfo& SetGlobalLocation(const Offset& globalLocation) 424 { 425 globalLocation_ = globalLocation; 426 return *this; 427 } SetLocalLocation(const Offset & localLocation)428 AccessibilityHoverInfo& SetLocalLocation(const Offset& localLocation) 429 { 430 localLocation_ = localLocation; 431 return *this; 432 } 433 SetScreenLocation(const Offset & screenLocation)434 AccessibilityHoverInfo& SetScreenLocation(const Offset& screenLocation) 435 { 436 screenLocation_ = screenLocation; 437 return *this; 438 } 439 GetScreenLocation()440 const Offset& GetScreenLocation() const 441 { 442 return screenLocation_; 443 } 444 GetLocalLocation()445 const Offset& GetLocalLocation() const 446 { 447 return localLocation_; 448 } 449 GetGlobalLocation()450 const Offset& GetGlobalLocation() const 451 { 452 return globalLocation_; 453 } 454 GetActionType()455 AccessibilityHoverAction GetActionType() const 456 { 457 return actionType_; 458 } 459 SetActionType(AccessibilityHoverAction type)460 void SetActionType(AccessibilityHoverAction type) 461 { 462 actionType_ = type; 463 } 464 465 private: 466 // global position at which the touch point contacts the screen. 467 Offset globalLocation_; 468 // Different from global location, The local location refers to the location of the contact point relative to the 469 // current node which has the recognizer. 470 Offset localLocation_; 471 472 Offset screenLocation_; 473 474 // touch type 475 AccessibilityHoverAction actionType_ = AccessibilityHoverAction::UNKNOWN; 476 }; 477 478 using OnHoverFunc = std::function<void(bool, HoverInfo& info)>; 479 using OnHoverMoveFunc = std::function<void(HoverInfo& info)>; 480 using OnHoverEventFunc = std::function<void(bool)>; 481 482 using OnAccessibilityHoverFunc = std::function<void(bool, AccessibilityHoverInfo& info)>; 483 484 class MouseEventTarget : public virtual TouchEventTarget { 485 DECLARE_ACE_TYPE(MouseEventTarget, TouchEventTarget); 486 487 public: MouseEventTarget(const std::string & nodeName,int32_t nodeId)488 MouseEventTarget(const std::string& nodeName, int32_t nodeId) : TouchEventTarget(nodeName, nodeId) {} 489 ~MouseEventTarget() override = default; 490 SetCallback(const OnMouseEventFunc & onMouseCallback)491 void SetCallback(const OnMouseEventFunc& onMouseCallback) 492 { 493 onMouseCallback_ = onMouseCallback; 494 } 495 HandleMouseEvent(const MouseEvent & event)496 bool HandleMouseEvent(const MouseEvent& event) 497 { 498 if (!onMouseCallback_) { 499 return false; 500 } 501 MouseInfo info; 502 info.SetPointerEvent(event.pointerEvent); 503 info.SetButton(event.button); 504 info.SetAction(event.action); 505 info.SetPullAction(event.pullAction); 506 info.SetGlobalLocation(event.GetOffset()); 507 Offset localLocation = Offset( 508 event.GetOffset().GetX() - coordinateOffset_.GetX(), event.GetOffset().GetY() - coordinateOffset_.GetY()); 509 info.SetLocalLocation(localLocation); 510 info.SetScreenLocation(event.GetScreenOffset()); 511 info.SetTimeStamp(event.time); 512 info.SetDeviceId(event.deviceId); 513 info.SetTargetDisplayId(event.targetDisplayId); 514 info.SetSourceDevice(event.sourceType); 515 info.SetSourceTool(event.sourceTool); 516 info.SetTarget(GetEventTarget().value_or(EventTarget())); 517 info.SetPressedKeyCodes(event.pressedKeyCodes_); 518 info.SetRawDeltaX(event.rawDeltaX); 519 info.SetRawDeltaY(event.rawDeltaY); 520 info.SetPressedButtons(event.pressedButtonsArray); 521 // onMouseCallback_ may be overwritten in its invoke so we copy it first 522 auto onMouseCallback = onMouseCallback_; 523 onMouseCallback(info); 524 return info.IsStopPropagation(); 525 } 526 DispatchEvent(const TouchEvent & point)527 bool DispatchEvent(const TouchEvent& point) override 528 { 529 return false; 530 } 531 // if return false means need to stop event bubbling. HandleEvent(const TouchEvent & point)532 bool HandleEvent(const TouchEvent& point) override 533 { 534 return false; 535 } 536 537 private: 538 OnMouseEventFunc onMouseCallback_; 539 }; 540 541 class HoverEventTarget : public virtual TouchEventTarget { 542 DECLARE_ACE_TYPE(HoverEventTarget, TouchEventTarget); 543 544 public: HoverEventTarget(const std::string & nodeName,int32_t nodeId)545 HoverEventTarget(const std::string& nodeName, int32_t nodeId) : TouchEventTarget(nodeName, nodeId) {} 546 ~HoverEventTarget() override = default; 547 SetCallback(const OnHoverEventFunc & onHoverCallback)548 void SetCallback(const OnHoverEventFunc& onHoverCallback) 549 { 550 onHoverCallback_ = onHoverCallback; 551 } SetCallback(const OnHoverFunc & onHoverEventCallback)552 void SetCallback(const OnHoverFunc& onHoverEventCallback) 553 { 554 onHoverEventCallback_ = onHoverEventCallback; 555 } 556 SetAccessibilityHoverCallback(const OnAccessibilityHoverFunc & onAccessibilityHoverCallback)557 void SetAccessibilityHoverCallback(const OnAccessibilityHoverFunc& onAccessibilityHoverCallback) 558 { 559 onAccessibilityHoverCallback_ = onAccessibilityHoverCallback; 560 } 561 SetPenHoverCallback(const OnHoverFunc & onPenHoverEventCallback)562 void SetPenHoverCallback(const OnHoverFunc& onPenHoverEventCallback) 563 { 564 onPenHoverEventCallback_ = onPenHoverEventCallback; 565 } 566 SetPenHoverMoveCallback(const OnHoverMoveFunc & onPenHoverMoveEventCallback)567 void SetPenHoverMoveCallback(const OnHoverMoveFunc& onPenHoverMoveEventCallback) 568 { 569 onPenHoverMoveEventCallback_ = onPenHoverMoveEventCallback; 570 } 571 572 bool HandleHoverEvent(bool isHovered, const MouseEvent& event); 573 574 void HandleAccessibilityHoverEvent(bool isHovered, const TouchEvent& event); 575 576 bool HandlePenHoverEvent(bool isHovered, const TouchEvent& event); 577 578 bool HandlePenHoverMoveEvent(const TouchEvent& event); 579 IsHoverTarget()580 bool IsHoverTarget() const 581 { 582 return onHoverCallback_ != nullptr || onHoverEventCallback_ != nullptr; 583 } 584 IsAccessibilityHoverTarget()585 bool IsAccessibilityHoverTarget() 586 { 587 return onAccessibilityHoverCallback_ != nullptr; 588 } 589 IsPenHoverTarget()590 bool IsPenHoverTarget() const 591 { 592 return onPenHoverEventCallback_ != nullptr; 593 } 594 IsPenHoverMoveTarget()595 bool IsPenHoverMoveTarget() const 596 { 597 return onPenHoverMoveEventCallback_ != nullptr; 598 } 599 HandleHoverEvent(bool isHovered)600 bool HandleHoverEvent(bool isHovered) 601 { 602 if (!onHoverCallback_) { 603 return false; 604 } 605 onHoverCallback_(isHovered); 606 return true; 607 } 608 DispatchEvent(const TouchEvent & point)609 bool DispatchEvent(const TouchEvent& point) override 610 { 611 return false; 612 } HandleEvent(const TouchEvent & point)613 bool HandleEvent(const TouchEvent& point) override 614 { 615 return false; 616 } 617 618 AccessibilityHoverAction ConvertAccessibilityHoverAction(TouchType type); 619 620 private: 621 OnHoverEventFunc onHoverCallback_; 622 OnHoverFunc onHoverEventCallback_; 623 OnAccessibilityHoverFunc onAccessibilityHoverCallback_; 624 OnHoverFunc onPenHoverEventCallback_; 625 OnHoverMoveFunc onPenHoverMoveEventCallback_; 626 }; 627 628 class HoverEffectTarget : public virtual TouchEventTarget { 629 DECLARE_ACE_TYPE(HoverEffectTarget, TouchEventTarget); 630 631 public: HoverEffectTarget(const std::string & nodeName,int32_t nodeId)632 HoverEffectTarget(const std::string& nodeName, int32_t nodeId) : TouchEventTarget(nodeName, nodeId) {} 633 ~HoverEffectTarget() override = default; 634 SetHoverNode(const WeakPtr<NG::FrameNode> & node)635 void SetHoverNode(const WeakPtr<NG::FrameNode>& node) 636 { 637 hoverNode_ = node; 638 } GetHoverNode()639 WeakPtr<NG::FrameNode> GetHoverNode() const 640 { 641 return hoverNode_; 642 } 643 DispatchEvent(const TouchEvent & point)644 bool DispatchEvent(const TouchEvent& point) override 645 { 646 return false; 647 } 648 // if return false means need to stop event bubbling. HandleEvent(const TouchEvent & point)649 bool HandleEvent(const TouchEvent& point) override 650 { 651 return false; 652 } 653 654 private: 655 WeakPtr<NG::FrameNode> hoverNode_; 656 }; 657 658 using MouseTestResult = std::list<RefPtr<MouseEventTarget>>; 659 using HoverTestResult = std::list<RefPtr<HoverEventTarget>>; 660 661 } // namespace OHOS::Ace 662 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_EVENT_MOUSE_EVENT_H 663