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