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