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 #include "core/components_ng/event/touch_event.h"
17 
18 #include "core/components_ng/event/response_ctrl.h"
19 #include "core/components_ng/gestures/recognizers/gesture_recognizer.h"
20 #include "core/pipeline_ng/pipeline_context.h"
21 
22 namespace OHOS::Ace::NG {
23 
DispatchEvent(const TouchEvent & point)24 bool TouchEventActuator::DispatchEvent(const TouchEvent& point)
25 {
26     return true;
27 }
28 
OnFlushTouchEventsBegin()29 void TouchEventActuator::OnFlushTouchEventsBegin()
30 {
31     isFlushTouchEventsEnd_ = false;
32 }
33 
OnFlushTouchEventsEnd()34 void TouchEventActuator::OnFlushTouchEventsEnd()
35 {
36     isFlushTouchEventsEnd_ = true;
37 }
38 
HandleEvent(const TouchEvent & point)39 bool TouchEventActuator::HandleEvent(const TouchEvent& point)
40 {
41     // if current node is forbidden by monopolize, upper nodes should not response either
42     if (!ShouldResponse()) {
43         return false;
44     }
45     return TriggerTouchCallBack(point);
46 }
47 
TriggerTouchCallBack(const TouchEvent & point)48 bool TouchEventActuator::TriggerTouchCallBack(const TouchEvent& point)
49 {
50     if (point.type == TouchType::DOWN &&
51         firstInputTimeWithId_.find(point.id) == firstInputTimeWithId_.end()) {
52         firstInputTimeWithId_[point.id] = point.time;
53     }
54     if (point.type == TouchType::UP &&
55         firstInputTimeWithId_.find(point.id) != firstInputTimeWithId_.end()) {
56         int64_t overTime = GetSysTimestamp();
57         int64_t inputTime = static_cast<int64_t>(firstInputTimeWithId_[point.id].time_since_epoch().count());
58         if (SystemProperties::GetTraceInputEventEnabled()) {
59             ACE_SCOPED_TRACE("UserEvent InputTime:%lld OverTime:%lld InputType:TouchEvent",
60                 static_cast<long long>(inputTime), static_cast<long long>(overTime));
61         }
62         if (SystemProperties::GetTraceInputEventEnabled()) {
63             ACE_SCOPED_TRACE("UserEvent InputTime:%lld AcceptTime:%lld InputType:TouchEvent",
64                 static_cast<long long>(inputTime), static_cast<long long>(overTime));
65         }
66         firstInputTimeWithId_.erase(point.id);
67     }
68 
69     if (touchEvents_.empty() && !touchAfterEvents_ && !userCallback_ && !onTouchEventCallback_ &&
70         !commonTouchEventCallback_) {
71         return true;
72     }
73     TouchEvent lastPoint;
74     if (point.isInterpolated) {
75         lastPoint = point;
76     } else {
77         lastPoint = !point.history.empty() ? point.history.back() : point;
78     }
79     auto event = CreateTouchEventInfo(lastPoint);
80     auto changedInfo = CreateChangedTouchInfo(lastPoint, point);
81     event.AddChangedTouchLocationInfo(std::move(changedInfo));
82     // all fingers collection
83     for (const auto& item : lastPoint.pointers) {
84         auto info = CreateTouchItemInfo(item, point, lastPoint.type);
85         event.AddTouchLocationInfo(std::move(info));
86     }
87     for (const auto& item : point.history) {
88         auto historyInfo = CreateHistoryTouchItemInfo(item, point);
89         event.AddHistoryLocationInfo(std::move(historyInfo));
90         event.AddHistoryPointerEvent(item.pointerEvent);
91     }
92     TriggerCallBacks(event);
93     return !event.IsStopPropagation();
94 }
95 
ShouldResponse()96 bool TouchEventActuator::ShouldResponse()
97 {
98     auto context = PipelineContext::GetCurrentContext();
99     CHECK_NULL_RETURN(context, true);
100 
101     auto eventManager = context->GetEventManager();
102     CHECK_NULL_RETURN(eventManager, true);
103 
104     auto frameNode = GetAttachedNode();
105     auto ctrl = eventManager->GetResponseCtrl();
106     CHECK_NULL_RETURN(ctrl, true);
107     if (!ctrl->ShouldResponse(frameNode)) {
108         return false;
109     }
110     ctrl->TrySetFirstResponse(frameNode);
111     return true;
112 }
113 
CreateTouchEventInfo(const TouchEvent & lastPoint)114 TouchEventInfo TouchEventActuator::CreateTouchEventInfo(const TouchEvent& lastPoint)
115 {
116     TouchEventInfo eventInfo("touchEvent");
117     eventInfo.SetTimeStamp(lastPoint.time);
118     eventInfo.SetPointerEvent(lastPoint.pointerEvent);
119     eventInfo.SetDeviceId(lastPoint.deviceId);
120     eventInfo.SetTarget(GetEventTarget().value_or(EventTarget()));
121     auto frameNode = GetAttachedNode().Upgrade();
122     std::string patternName = "";
123     if (frameNode) {
124         patternName = frameNode->GetTag();
125     }
126     eventInfo.SetPatternName(patternName.c_str());
127     eventInfo.SetSourceDevice(lastPoint.sourceType);
128     eventInfo.SetForce(lastPoint.force);
129     if (lastPoint.tiltX.has_value()) {
130         eventInfo.SetTiltX(lastPoint.tiltX.value());
131     }
132     if (lastPoint.tiltY.has_value()) {
133         eventInfo.SetTiltY(lastPoint.tiltY.value());
134     }
135     eventInfo.SetSourceTool(lastPoint.sourceTool);
136     eventInfo.SetPressedKeyCodes(lastPoint.pressedKeyCodes_);
137     if (isFlushTouchEventsEnd_) {
138         // trigger callback of the last touch event during one vsync period
139         eventInfo.SetTouchEventsEnd(true);
140         isFlushTouchEventsEnd_ = false;
141     }
142     return eventInfo;
143 }
144 
CreateChangedTouchInfo(const TouchEvent & lastPoint,const TouchEvent & event)145 TouchLocationInfo TouchEventActuator::CreateChangedTouchInfo(const TouchEvent& lastPoint, const TouchEvent& event)
146 {
147     TouchLocationInfo changedInfo("onTouch", lastPoint.originalId);
148     PointF lastLocalPoint(lastPoint.x, lastPoint.y);
149     NGGestureRecognizer::Transform(lastLocalPoint, GetAttachedNode(), false, isPostEventResult_, event.postEventNodeId);
150     auto localX = static_cast<float>(lastLocalPoint.GetX());
151     auto localY = static_cast<float>(lastLocalPoint.GetY());
152     changedInfo.SetLocalLocation(Offset(localX, localY));
153     changedInfo.SetGlobalLocation(Offset(lastPoint.x, lastPoint.y));
154     changedInfo.SetScreenLocation(Offset(lastPoint.screenX, lastPoint.screenY));
155     changedInfo.SetTouchType(lastPoint.type);
156     changedInfo.SetForce(lastPoint.force);
157     if (lastPoint.tiltX.has_value()) {
158         changedInfo.SetTiltX(lastPoint.tiltX.value());
159     }
160     if (lastPoint.tiltY.has_value()) {
161         changedInfo.SetTiltY(lastPoint.tiltY.value());
162     }
163     changedInfo.SetSourceTool(lastPoint.sourceTool);
164     return changedInfo;
165 }
166 
CreateTouchItemInfo(const TouchPoint & pointItem,const TouchEvent & event,TouchType type)167 TouchLocationInfo TouchEventActuator::CreateTouchItemInfo(
168     const TouchPoint& pointItem, const TouchEvent& event, TouchType type)
169 {
170     float globalX = pointItem.x;
171     float globalY = pointItem.y;
172     float screenX = pointItem.screenX;
173     float screenY = pointItem.screenY;
174     PointF localPoint(globalX, globalY);
175     NGGestureRecognizer::Transform(localPoint, GetAttachedNode(), false, isPostEventResult_, event.postEventNodeId);
176     auto localX = static_cast<float>(localPoint.GetX());
177     auto localY = static_cast<float>(localPoint.GetY());
178     TouchLocationInfo info("onTouch", pointItem.originalId);
179     info.SetGlobalLocation(Offset(globalX, globalY));
180     info.SetLocalLocation(Offset(localX, localY));
181     info.SetScreenLocation(Offset(screenX, screenY));
182     info.SetTouchType(type);
183     info.SetForce(pointItem.force);
184     if (pointItem.tiltX.has_value()) {
185         info.SetTiltX(pointItem.tiltX.value());
186     }
187     if (pointItem.tiltY.has_value()) {
188         info.SetTiltY(pointItem.tiltY.value());
189     }
190     info.SetSourceTool(pointItem.sourceTool);
191     return info;
192 }
193 
CreateHistoryTouchItemInfo(const TouchEvent & eventItem,const TouchEvent & event)194 TouchLocationInfo TouchEventActuator::CreateHistoryTouchItemInfo(const TouchEvent& eventItem, const TouchEvent& event)
195 {
196     float globalX = eventItem.x;
197     float globalY = eventItem.y;
198     float screenX = eventItem.screenX;
199     float screenY = eventItem.screenY;
200     PointF localPoint(globalX, globalY);
201     NGGestureRecognizer::Transform(localPoint, GetAttachedNode(), false, isPostEventResult_, event.postEventNodeId);
202     auto localX = static_cast<float>(localPoint.GetX());
203     auto localY = static_cast<float>(localPoint.GetY());
204     TouchLocationInfo historyInfo("onTouch", eventItem.originalId);
205     historyInfo.SetTimeStamp(eventItem.time);
206     historyInfo.SetGlobalLocation(Offset(globalX, globalY));
207     historyInfo.SetLocalLocation(Offset(localX, localY));
208     historyInfo.SetScreenLocation(Offset(screenX, screenY));
209     historyInfo.SetTouchType(eventItem.type);
210     historyInfo.SetForce(eventItem.force);
211     if (eventItem.tiltX.has_value()) {
212         historyInfo.SetTiltX(eventItem.tiltX.value());
213     }
214     if (eventItem.tiltY.has_value()) {
215         historyInfo.SetTiltY(eventItem.tiltY.value());
216     }
217     historyInfo.SetSourceTool(eventItem.sourceTool);
218     return historyInfo;
219 }
220 
TriggerCallBacks(TouchEventInfo & event)221 void TouchEventActuator::TriggerCallBacks(TouchEventInfo& event)
222 {
223     for (auto& impl : touchEvents_) {
224         if (impl) {
225             (*impl)(event);
226         }
227     }
228     if (userCallback_) {
229         // actuator->userCallback_ may be overwritten in its invoke so we copy it first
230         auto userCallback = userCallback_;
231         (*userCallback)(event);
232     }
233     if (touchAfterEvents_) {
234         auto touchAfterEvents = touchAfterEvents_;
235         (*touchAfterEvents)(event);
236     }
237     if (onTouchEventCallback_) {
238         // actuator->onTouchEventCallback_ may be overwritten in its invoke so we copy it first
239         auto onTouchEventCallback = onTouchEventCallback_;
240         (*onTouchEventCallback)(event);
241     }
242     if (commonTouchEventCallback_) {
243         // actuator->commonTouchEventCallback_ may be overwritten in its invoke so we copy it first
244         auto commonTouchEventCallback = commonTouchEventCallback_;
245         (*commonTouchEventCallback)(event);
246     }
247 }
248 
249 } // namespace OHOS::Ace::NG