• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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