• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 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_AXIS_EVENT_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_EVENT_AXIS_EVENT_H
18 
19 #include <list>
20 #include <utility>
21 
22 #include "base/geometry/offset.h"
23 #include "base/memory/ace_type.h"
24 #include "core/components_ng/event/event_constants.h"
25 #include "core/event/ace_events.h"
26 
27 namespace OHOS::MMI {
28 class PointerEvent;
29 } // namespace OHOS::MMI
30 
31 namespace OHOS::Ace {
32 
33 constexpr double MOUSE_WHEEL_DEGREES = 15.0;
34 constexpr double DP_PER_LINE_DESKTOP = 40.0;
35 constexpr Dimension LINE_HEIGHT_DESKTOP = 21.0_vp;
36 constexpr int32_t LINE_NUMBER_DESKTOP = 3;
37 constexpr int32_t DP_PER_LINE_PHONE = 64;
38 constexpr int32_t LINE_NUMBER_PHONE = 1;
39 
40 enum class AxisDirection : int32_t {
41     NONE = 0,
42     UP = 1,
43     DOWN = 2,
44     LEFT = 4,
45     RIGHT = 8,
46     UP_LEFT = 5,
47     UP_RIGHT = 9,
48     DOWN_LEFT = 6,
49     DOWN_RIGHT = 10,
50 };
51 
52 enum class AxisAction : int32_t {
53     NONE = 0,
54     BEGIN,
55     UPDATE,
56     END,
57     CANCEL,
58 };
59 
60 struct UIInputEvent {
61     virtual ~UIInputEvent() = default;
62     TimeStamp time;
63     UIInputEventType eventType = UIInputEventType::NONE;
64 };
65 
66 
67 struct PointerEvent : public UIInputEvent {
68     virtual ~PointerEvent() = default;
69     explicit PointerEvent(float x = {}, float y = {}, float screenX = {},
70         float screenY = {}, TimeStamp time = {})
xPointerEvent71         :x(x), y(y), screenX(screenX), screenY(screenY)
72     {
73         this->time = time;
74     }
75     float x = {};
76     float y = {};
77     float screenX = {};
78     float screenY = {};
79 };
80 
81 struct AxisEvent final : public PointerEvent {
82     ~AxisEvent() = default;
83     int32_t id = 0;
84 
85     double verticalAxis = 0.0;
86     double horizontalAxis = 0.0;
87     double pinchAxisScale = 0.0;
88     double rotateAxisAngle = 0.0;
89     bool isRotationEvent = false;
90     AxisAction action = AxisAction::NONE;
91     int64_t deviceId = 0;
92     SourceType sourceType = SourceType::NONE;
93     SourceTool sourceTool = SourceTool::UNKNOWN;
94     std::shared_ptr<MMI::PointerEvent> pointerEvent;
95     int32_t touchEventId = 0;
96     std::vector<KeyCode> pressedCodes;
97 
98     // Coordinates relative to the upper-left corner of the current component
99     float localX = 0.0;
100     float localY = 0.0;
101 
102     int32_t targetDisplayId = 0;
103     int32_t originalId = 0;
104     bool isInjected = false;
105 
AxisEventfinal106     AxisEvent()
107     {
108         eventType = UIInputEventType::AXIS;
109     }
110 
AxisEventfinal111     AxisEvent(int32_t id, float x, float y, float screenX, float screenY, double verticalAxis, double horizontalAxis,
112         double pinchAxisScale, double rotateAxisAngle, bool isRotationEvent, AxisAction action, TimeStamp timestamp,
113         int64_t deviceId, SourceType sourceType, SourceTool sourceTool, std::shared_ptr<MMI::PointerEvent> pointerEvent,
114         std::vector<KeyCode> pressedCodes, int32_t targetDisplayId, int32_t originalId, bool isInjected)
115         : PointerEvent(x, y, screenX, screenY, timestamp), id(id), verticalAxis(verticalAxis),
116         horizontalAxis(horizontalAxis), pinchAxisScale(pinchAxisScale), rotateAxisAngle(rotateAxisAngle),
117         isRotationEvent(isRotationEvent), action(action), deviceId(deviceId), sourceType(sourceType),
118         sourceTool(sourceTool), pointerEvent(std::move(pointerEvent)), pressedCodes(pressedCodes),
119         targetDisplayId(targetDisplayId), originalId(originalId), isInjected(isInjected)
120     {
121         eventType = UIInputEventType::AXIS;
122     }
123 
CreateScaleEventfinal124     AxisEvent CreateScaleEvent(float scale) const
125     {
126         if (NearZero(scale)) {
127             return { id, x, y, screenX, screenY, verticalAxis, horizontalAxis, pinchAxisScale, rotateAxisAngle,
128                 isRotationEvent, action, time, deviceId, sourceType, sourceTool, pointerEvent, pressedCodes,
129                 targetDisplayId, originalId, isInjected };
130         }
131         return { id, x / scale, y / scale, screenX / scale, screenY / scale, verticalAxis, horizontalAxis,
132             pinchAxisScale, rotateAxisAngle, isRotationEvent, action, time, deviceId, sourceType, sourceTool,
133             pointerEvent, pressedCodes, targetDisplayId, originalId, isInjected };
134     }
135 
GetOffsetfinal136     Offset GetOffset() const
137     {
138         return Offset(x, y);
139     }
140 
GetScreenOffsetfinal141     Offset GetScreenOffset() const
142     {
143         return Offset(screenX, screenY);
144     }
145 
GetDirectionfinal146     AxisDirection GetDirection() const
147     {
148         uint32_t verticalFlag = 0;
149         uint32_t horizontalFlag = 0;
150         if (LessNotEqual(verticalAxis, 0.0)) {
151             verticalFlag = static_cast<uint32_t>(AxisDirection::UP);
152         } else if (GreatNotEqual(verticalAxis, 0.0)) {
153             verticalFlag = static_cast<uint32_t>(AxisDirection::DOWN);
154         }
155         if (LessNotEqual(horizontalAxis, 0.0)) {
156             horizontalFlag = static_cast<uint32_t>(AxisDirection::LEFT);
157         } else if (GreatNotEqual(horizontalAxis, 0.0)) {
158             horizontalFlag = static_cast<uint32_t>(AxisDirection::RIGHT);
159         }
160         return static_cast<AxisDirection>(verticalFlag | horizontalFlag);
161     }
IsDirectionUpfinal162     static bool IsDirectionUp(AxisDirection direction)
163     {
164         return (static_cast<uint32_t>(direction) & static_cast<uint32_t>(AxisDirection::UP));
165     }
IsDirectionDownfinal166     static bool IsDirectionDown(AxisDirection direction)
167     {
168         return (static_cast<uint32_t>(direction) & static_cast<uint32_t>(AxisDirection::DOWN));
169     }
IsDirectionLeftfinal170     static bool IsDirectionLeft(AxisDirection direction)
171     {
172         return (static_cast<uint32_t>(direction) & static_cast<uint32_t>(AxisDirection::LEFT));
173     }
IsDirectionRightfinal174     static bool IsDirectionRight(AxisDirection direction)
175     {
176         return (static_cast<uint32_t>(direction) & static_cast<uint32_t>(AxisDirection::RIGHT));
177     }
178 
179     Offset ConvertToOffset(bool isShiftKeyPressed = false, bool hasDifferentDirectionGesture = false) const
180     {
181         Offset result;
182         if (sourceTool == SourceTool::MOUSE) {
183             // Axis event is made by mouse.
184             if (isShiftKeyPressed) {
185                 result = Offset(-verticalAxis, -horizontalAxis);
186             } else {
187                 if (hasDifferentDirectionGesture) {
188                     result = Offset(-horizontalAxis, -verticalAxis);
189                 } else {
190                     result = Offset(-verticalAxis, -verticalAxis);
191                 }
192             }
193             return result * (LINE_HEIGHT_DESKTOP / MOUSE_WHEEL_DEGREES).ConvertToPx();
194         }
195         // Axis event is made by others. Include touch-pad.
196         result = Offset(-horizontalAxis, -verticalAxis);
197         return result;
198     }
199 
200     // MMI has the different direction, need to check truth direction.
ConvertToSummationAxisValuefinal201     std::pair<float, float> ConvertToSummationAxisValue(const AxisEvent& event) const
202     {
203         return std::make_pair(event.horizontalAxis - horizontalAxis, event.verticalAxis - verticalAxis);
204     }
205 };
206 
207 class AxisInfo : public BaseEventInfo {
208     DECLARE_RELATIONSHIP_OF_CLASSES(AxisInfo, BaseEventInfo);
209 
210 public:
AxisInfo()211     AxisInfo() : BaseEventInfo("onAxis") {}
AxisInfo(const AxisEvent & event,const Offset & localLocation,const EventTarget & target)212     AxisInfo(const AxisEvent& event, const Offset& localLocation, const EventTarget& target) : BaseEventInfo("onAxis")
213     {
214         action_ = event.action;
215         verticalAxis_ = static_cast<float>(event.verticalAxis);
216         horizontalAxis_ = static_cast<float>(event.horizontalAxis);
217         pinchAxisScale_ = static_cast<float>(event.pinchAxisScale);
218         rotateAxisAngle_ = static_cast<float>(event.rotateAxisAngle);
219         isRotationEvent_ = event.isRotationEvent;
220         globalLocation_ = event.GetOffset();
221         localLocation_ = localLocation;
222         screenLocation_ = Offset();
223         SetTimeStamp(event.time);
224         SetDeviceId(event.deviceId);
225         SetSourceDevice(event.sourceType);
226         SetTarget(target);
227     }
228     ~AxisInfo() override = default;
229 
SetAction(AxisAction action)230     void SetAction(AxisAction action)
231     {
232         action_ = action;
233     }
234 
GetAction()235     AxisAction GetAction() const
236     {
237         return action_;
238     }
239 
SetVerticalAxis(float axis)240     void SetVerticalAxis(float axis)
241     {
242         verticalAxis_ = axis;
243     }
244 
GetVerticalAxis()245     float GetVerticalAxis() const
246     {
247         return verticalAxis_;
248     }
249 
SetHorizontalAxis(float axis)250     void SetHorizontalAxis(float axis)
251     {
252         horizontalAxis_ = axis;
253     }
254 
GetHorizontalAxis()255     float GetHorizontalAxis() const
256     {
257         return horizontalAxis_;
258     }
259 
SetPinchAxisScale(float scale)260     void SetPinchAxisScale(float scale)
261     {
262         pinchAxisScale_ = scale;
263     }
264 
GetPinchAxisScale()265     float GetPinchAxisScale() const
266     {
267         return pinchAxisScale_;
268     }
269 
SetRotateAxisAngle(float angle)270     void SetRotateAxisAngle(float angle)
271     {
272         rotateAxisAngle_ = angle;
273     }
274 
GetRotateAxisAngle()275     float GetRotateAxisAngle() const
276     {
277         return rotateAxisAngle_;
278     }
279 
SetIsRotationEvent(bool rotationFlag)280     void SetIsRotationEvent(bool rotationFlag)
281     {
282         isRotationEvent_ = rotationFlag;
283     }
284 
GetIsRotationEvent()285     bool GetIsRotationEvent() const
286     {
287         return isRotationEvent_;
288     }
289 
SetGlobalLocation(const Offset & globalLocation)290     AxisInfo& SetGlobalLocation(const Offset& globalLocation)
291     {
292         globalLocation_ = globalLocation;
293         return *this;
294     }
SetLocalLocation(const Offset & localLocation)295     AxisInfo& SetLocalLocation(const Offset& localLocation)
296     {
297         localLocation_ = localLocation;
298         return *this;
299     }
300 
SetScreenLocation(const Offset & screenLocation)301     AxisInfo& SetScreenLocation(const Offset& screenLocation)
302     {
303         screenLocation_ = screenLocation;
304         return *this;
305     }
306 
GetScreenLocation()307     const Offset& GetScreenLocation() const
308     {
309         return screenLocation_;
310     }
311 
GetLocalLocation()312     const Offset& GetLocalLocation() const
313     {
314         return localLocation_;
315     }
GetGlobalLocation()316     const Offset& GetGlobalLocation() const
317     {
318         return globalLocation_;
319     }
320 
ConvertToAxisEvent()321     AxisEvent ConvertToAxisEvent() const
322     {
323         AxisEvent axisEvent;
324         axisEvent.x = static_cast<float>(globalLocation_.GetX());
325         axisEvent.y = static_cast<float>(globalLocation_.GetY());
326         axisEvent.screenX = static_cast<float>(screenLocation_.GetX());
327         axisEvent.screenY = static_cast<float>(screenLocation_.GetY());
328         axisEvent.horizontalAxis = horizontalAxis_;
329         axisEvent.verticalAxis = verticalAxis_;
330         axisEvent.pinchAxisScale = pinchAxisScale_;
331         axisEvent.action = action_;
332         axisEvent.rotateAxisAngle = rotateAxisAngle_;
333         axisEvent.time = timeStamp_;
334         axisEvent.localX = static_cast<float>(localLocation_.GetX());
335         axisEvent.localY = static_cast<float>(localLocation_.GetY());
336         axisEvent.sourceType = deviceType_;
337         axisEvent.sourceTool = sourceTool_;
338         return axisEvent;
339     }
340 
341 private:
342     AxisAction action_ = AxisAction::NONE;
343     float verticalAxis_ = 0.0;
344     float horizontalAxis_ = 0.0;
345     float pinchAxisScale_ = 0.0;
346     float rotateAxisAngle_ = 0.0;
347     bool isRotationEvent_ = false;
348     // global position at which the touch point contacts the screen.
349     Offset globalLocation_;
350     // Different from global location, The local location refers to the location of the contact point relative to the
351     // current node which has the recognizer.
352     Offset localLocation_;
353     Offset screenLocation_;
354 };
355 
356 using OnAxisEventFunc = std::function<void(AxisInfo&)>;
357 using GetEventTargetImpl = std::function<std::optional<EventTarget>()>;
358 
359 class AxisEventTarget : public virtual AceType {
360     DECLARE_ACE_TYPE(AxisEventTarget, AceType);
361 
362 public:
363     AxisEventTarget() = default;
AxisEventTarget(std::string frameName)364     AxisEventTarget(std::string frameName) : frameName_(std::move(frameName)) {}
365     ~AxisEventTarget() override = default;
366 
SetOnAxisCallback(const OnAxisEventFunc & onAxisCallback)367     void SetOnAxisCallback(const OnAxisEventFunc& onAxisCallback)
368     {
369         onAxisCallback_ = onAxisCallback;
370     }
371 
SetCoordinateOffset(const NG::OffsetF & coordinateOffset)372     void SetCoordinateOffset(const NG::OffsetF& coordinateOffset)
373     {
374         coordinateOffset_ = coordinateOffset;
375     }
376 
SetGetEventTargetImpl(const GetEventTargetImpl & getEventTargetImpl)377     void SetGetEventTargetImpl(const GetEventTargetImpl& getEventTargetImpl)
378     {
379         getEventTargetImpl_ = getEventTargetImpl;
380     }
381 
GetEventTarget()382     std::optional<EventTarget> GetEventTarget() const
383     {
384         if (getEventTargetImpl_) {
385             return getEventTargetImpl_();
386         }
387         return std::nullopt;
388     }
389 
SetFrameName(const std::string & frameName)390     void SetFrameName(const std::string& frameName)
391     {
392         frameName_ = frameName;
393     }
394 
GetFrameName()395     std::string GetFrameName() const
396     {
397         return frameName_;
398     }
399 
HandleAxisEvent(const AxisEvent & event)400     bool HandleAxisEvent(const AxisEvent& event)
401     {
402         if (!onAxisCallback_) {
403             return false;
404         }
405         Offset localLocation = Offset(
406             event.GetOffset().GetX() - coordinateOffset_.GetX(), event.GetOffset().GetY() - coordinateOffset_.GetY());
407         AxisInfo info = AxisInfo(event, localLocation, GetEventTarget().value_or(EventTarget()));
408         info.SetScreenLocation(Offset(event.screenX, event.screenY));
409         info.SetSourceTool(event.sourceTool);
410         onAxisCallback_(info);
411         return true;
412     }
413 
HandleEvent(const AxisEvent & event)414     virtual void HandleEvent(const AxisEvent& event) {}
415 
416 private:
417     OnAxisEventFunc onAxisCallback_;
418     NG::OffsetF coordinateOffset_;
419     GetEventTargetImpl getEventTargetImpl_;
420     std::string frameName_ = "Unknown";
421 };
422 
423 using AxisTestResult = std::list<RefPtr<AxisEventTarget>>;
424 
425 } // namespace OHOS::Ace
426 
427 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_EVENT_AXIS_EVENT_H