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_MOUSE_EVENT_H 17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_EVENT_MOUSE_EVENT_H 18 19 #include "base/geometry/ng/offset_t.h" 20 #include "base/geometry/offset.h" 21 #include "base/mousestyle/mouse_style.h" 22 #include "core/event/touch_event.h" 23 #include "core/pipeline_ng/ui_task_scheduler.h" 24 25 namespace OHOS::Ace { 26 27 class MouseInfo; 28 29 constexpr int32_t MOUSE_PRESS_LEFT = 1; 30 static const int32_t MOUSE_BASE_ID = 1000; 31 32 using OnHoverEventFunc = std::function<void(bool)>; 33 using OnMouseEventFunc = std::function<void(MouseInfo& info)>; 34 35 enum class MouseAction : int32_t { 36 NONE = 0, 37 PRESS = 1, 38 RELEASE = 2, 39 MOVE = 3, 40 WINDOW_ENTER = 4, 41 WINDOW_LEAVE = 5, 42 HOVER, 43 HOVER_ENTER, 44 HOVER_MOVE, 45 HOVER_EXIT, 46 }; 47 48 enum class MouseState : int32_t { 49 NONE = 0, 50 HOVER = 1, 51 }; 52 53 enum class MouseButton : int32_t { 54 NONE_BUTTON = 0, 55 LEFT_BUTTON = 1, 56 RIGHT_BUTTON = 2, 57 MIDDLE_BUTTON = 4, 58 BACK_BUTTON = 8, 59 FORWARD_BUTTON = 16, 60 SIDE_BUTTON = 32, 61 EXTRA_BUTTON = 64, 62 TASK_BUTTON = 128, 63 }; 64 65 enum class HoverEffectType : int32_t { 66 NONE, 67 OPACITY, 68 SCALE, 69 BOARD, 70 AUTO, 71 UNKNOWN, 72 }; 73 74 struct MouseEvent final { 75 float x = 0.0f; 76 float y = 0.0f; 77 float z = 0.0f; 78 float deltaX = 0.0f; 79 float deltaY = 0.0f; 80 float deltaZ = 0.0f; 81 float scrollX = 0.0f; 82 float scrollY = 0.0f; 83 float scrollZ = 0.0f; 84 float screenX = 0.0f; 85 float screenY = 0.0f; 86 MouseAction action = MouseAction::NONE; 87 MouseButton button = MouseButton::NONE_BUTTON; 88 int32_t pressedButtons = 0; // combined by MouseButtons 89 TimeStamp time; 90 int64_t deviceId = 0; 91 SourceType sourceType = SourceType::NONE; 92 GetOffsetfinal93 Offset GetOffset() const 94 { 95 return Offset(x, y); 96 } 97 GetScreenOffsetfinal98 Offset GetScreenOffset() const 99 { 100 return Offset(screenX, screenY); 101 } 102 GetIdfinal103 int32_t GetId() const 104 { 105 if (pressedButtons > 0) { 106 return pressedButtons + MOUSE_BASE_ID; 107 } else { 108 return (int32_t)button + MOUSE_BASE_ID; 109 } 110 } 111 CreateScaleEventfinal112 MouseEvent CreateScaleEvent(float scale) const 113 { 114 if (NearZero(scale)) { 115 return { .x = x, 116 .y = y, 117 .z = z, 118 .deltaX = deltaX, 119 .deltaY = deltaY, 120 .deltaZ = deltaZ, 121 .scrollX = scrollX, 122 .scrollY = scrollY, 123 .scrollZ = scrollZ, 124 .screenX = screenX, 125 .screenY = screenY, 126 .action = action, 127 .button = button, 128 .pressedButtons = pressedButtons, 129 .time = time, 130 .deviceId = deviceId, 131 .sourceType = sourceType }; 132 } 133 134 return { .x = x / scale, 135 .y = y / scale, 136 .z = z / scale, 137 .deltaX = deltaX / scale, 138 .deltaY = deltaY / scale, 139 .deltaZ = deltaZ / scale, 140 .scrollX = scrollX / scale, 141 .scrollY = scrollY / scale, 142 .scrollZ = scrollZ / scale, 143 .screenX = screenX / scale, 144 .screenY = screenY / scale, 145 .action = action, 146 .button = button, 147 .pressedButtons = pressedButtons, 148 .time = time, 149 .deviceId = deviceId, 150 .sourceType = sourceType }; 151 } 152 CreateTouchPointfinal153 TouchEvent CreateTouchPoint() const 154 { 155 TouchType type = TouchType::UNKNOWN; 156 if (action == MouseAction::PRESS) { 157 type = TouchType::DOWN; 158 } else if (action == MouseAction::RELEASE) { 159 type = TouchType::UP; 160 } else if (action == MouseAction::MOVE) { 161 type = TouchType::MOVE; 162 } else { 163 type = TouchType::UNKNOWN; 164 } 165 int32_t id = GetId(); 166 TouchPoint point { .id = id, 167 .x = x, 168 .y = y, 169 .screenX = screenX, 170 .screenY = screenY, 171 .downTime = time, 172 .size = 0.0, 173 .isPressed = (type == TouchType::DOWN) }; 174 TouchEvent event { .id = id, 175 .x = x, 176 .y = y, 177 .screenX = screenX, 178 .screenY = screenY, 179 .type = type, 180 .time = time, 181 .size = 0.0, 182 .deviceId = deviceId, 183 .sourceType = sourceType }; 184 event.pointers.emplace_back(std::move(point)); 185 return event; 186 } 187 188 MouseEvent operator-(const Offset& offset) const 189 { 190 return { .x = x - offset.GetX(), 191 .y = y - offset.GetY(), 192 .z = z, 193 .deltaX = deltaX, 194 .deltaY = deltaY, 195 .deltaZ = deltaZ, 196 .scrollX = scrollX, 197 .scrollY = scrollY, 198 .scrollZ = scrollZ, 199 .screenX = screenX - offset.GetX(), 200 .screenY = screenY - offset.GetY(), 201 .action = action, 202 .button = button, 203 .pressedButtons = pressedButtons, 204 .time = time, 205 .deviceId = deviceId, 206 .sourceType = sourceType }; 207 } 208 }; 209 210 class MouseInfo : public BaseEventInfo { 211 DECLARE_RELATIONSHIP_OF_CLASSES(MouseInfo, BaseEventInfo); 212 213 public: MouseInfo()214 MouseInfo() : BaseEventInfo("onMouse") {} 215 ~MouseInfo() override = default; 216 SetButton(MouseButton button)217 void SetButton(MouseButton button) 218 { 219 button_ = button; 220 } 221 GetButton()222 MouseButton GetButton() const 223 { 224 return button_; 225 } 226 SetAction(MouseAction action)227 void SetAction(MouseAction action) 228 { 229 action_ = action; 230 } 231 GetAction()232 MouseAction GetAction() const 233 { 234 return action_; 235 } 236 SetGlobalLocation(const Offset & globalLocation)237 MouseInfo& SetGlobalLocation(const Offset& globalLocation) 238 { 239 globalLocation_ = globalLocation; 240 return *this; 241 } SetLocalLocation(const Offset & localLocation)242 MouseInfo& SetLocalLocation(const Offset& localLocation) 243 { 244 localLocation_ = localLocation; 245 return *this; 246 } 247 SetScreenLocation(const Offset & screenLocation)248 MouseInfo& SetScreenLocation(const Offset& screenLocation) 249 { 250 screenLocation_ = screenLocation; 251 return *this; 252 } 253 GetScreenLocation()254 const Offset& GetScreenLocation() const 255 { 256 return screenLocation_; 257 } 258 GetLocalLocation()259 const Offset& GetLocalLocation() const 260 { 261 return localLocation_; 262 } GetGlobalLocation()263 const Offset& GetGlobalLocation() const 264 { 265 return globalLocation_; 266 } 267 268 private: 269 MouseButton button_ = MouseButton::NONE_BUTTON; 270 MouseAction action_ = MouseAction::NONE; 271 // global position at which the touch point contacts the screen. 272 Offset globalLocation_; 273 // Different from global location, The local location refers to the location of the contact point relative to the 274 // current node which has the recognizer. 275 Offset localLocation_; 276 Offset screenLocation_; 277 }; 278 279 using HoverEffectFunc = std::function<void(bool)>; 280 281 class MouseEventTarget : public virtual TouchEventTarget { 282 DECLARE_ACE_TYPE(MouseEventTarget, TouchEventTarget); 283 284 public: MouseEventTarget(const std::string & nodeName,int32_t nodeId)285 MouseEventTarget(const std::string& nodeName, int32_t nodeId) : TouchEventTarget(nodeName, nodeId) {} 286 ~MouseEventTarget() override = default; 287 SetCallback(const OnMouseEventFunc & onMouseCallback)288 void SetCallback(const OnMouseEventFunc& onMouseCallback) 289 { 290 onMouseCallback_ = onMouseCallback; 291 } 292 HandleMouseEvent(const MouseEvent & event)293 bool HandleMouseEvent(const MouseEvent& event) 294 { 295 if (!onMouseCallback_) { 296 return false; 297 } 298 MouseInfo info; 299 info.SetButton(event.button); 300 info.SetAction(event.action); 301 info.SetGlobalLocation(event.GetOffset()); 302 Offset localLocation = Offset( 303 event.GetOffset().GetX() - coordinateOffset_.GetX(), event.GetOffset().GetY() - coordinateOffset_.GetY()); 304 info.SetLocalLocation(localLocation); 305 info.SetScreenLocation(event.GetScreenOffset()); 306 info.SetTimeStamp(event.time); 307 info.SetDeviceId(event.deviceId); 308 info.SetSourceDevice(event.sourceType); 309 info.SetTarget(GetEventTarget().value_or(EventTarget())); 310 onMouseCallback_(info); 311 return info.IsStopPropagation(); 312 } 313 DispatchEvent(const TouchEvent & point)314 bool DispatchEvent(const TouchEvent& point) override 315 { 316 return false; 317 } 318 // if return false means need to stop event bubbling. HandleEvent(const TouchEvent & point)319 bool HandleEvent(const TouchEvent& point) override 320 { 321 return false; 322 } 323 324 private: 325 OnMouseEventFunc onMouseCallback_; 326 }; 327 328 class HoverEventTarget : public virtual TouchEventTarget { 329 DECLARE_ACE_TYPE(HoverEventTarget, TouchEventTarget); 330 331 public: HoverEventTarget(const std::string & nodeName,int32_t nodeId)332 HoverEventTarget(const std::string& nodeName, int32_t nodeId) : TouchEventTarget(nodeName, nodeId) {} 333 ~HoverEventTarget() override = default; 334 SetCallback(const OnHoverEventFunc & onHoverCallback)335 void SetCallback(const OnHoverEventFunc& onHoverCallback) 336 { 337 onHoverCallback_ = onHoverCallback; 338 } 339 HandleHoverEvent(bool isHovered)340 bool HandleHoverEvent(bool isHovered) 341 { 342 if (!onHoverCallback_) { 343 return false; 344 } 345 onHoverCallback_(isHovered); 346 return true; 347 } 348 DispatchEvent(const TouchEvent & point)349 bool DispatchEvent(const TouchEvent& point) override 350 { 351 return false; 352 } HandleEvent(const TouchEvent & point)353 bool HandleEvent(const TouchEvent& point) override 354 { 355 return false; 356 } 357 358 private: 359 OnHoverEventFunc onHoverCallback_; 360 }; 361 362 class HoverEffectTarget : public virtual TouchEventTarget { 363 DECLARE_ACE_TYPE(HoverEffectTarget, TouchEventTarget); 364 365 public: HoverEffectTarget(const std::string & nodeName,int32_t nodeId)366 HoverEffectTarget(const std::string& nodeName, int32_t nodeId) : TouchEventTarget(nodeName, nodeId) {} 367 ~HoverEffectTarget() override = default; 368 SetHoverNode(const WeakPtr<NG::FrameNode> & node)369 void SetHoverNode(const WeakPtr<NG::FrameNode>& node) 370 { 371 hoverNode_ = node; 372 } GetHoverNode()373 WeakPtr<NG::FrameNode> GetHoverNode() const 374 { 375 return hoverNode_; 376 } 377 DispatchEvent(const TouchEvent & point)378 bool DispatchEvent(const TouchEvent& point) override 379 { 380 return false; 381 } 382 // if return false means need to stop event bubbling. HandleEvent(const TouchEvent & point)383 bool HandleEvent(const TouchEvent& point) override 384 { 385 return false; 386 } 387 388 private: 389 WeakPtr<NG::FrameNode> hoverNode_; 390 }; 391 392 using MouseTestResult = std::list<RefPtr<MouseEventTarget>>; 393 using HoverTestResult = std::list<RefPtr<HoverEventTarget>>; 394 395 } // namespace OHOS::Ace 396 397 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_EVENT_MOUSE_EVENT_H 398