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 eventInfo.SetOperatingHand(lastPoint.operatingHand);
138 if (isFlushTouchEventsEnd_) {
139 // trigger callback of the last touch event during one vsync period
140 eventInfo.SetTouchEventsEnd(true);
141 isFlushTouchEventsEnd_ = false;
142 }
143 eventInfo.SetTargetDisplayId(lastPoint.targetDisplayId);
144 return eventInfo;
145 }
146
CreateChangedTouchInfo(const TouchEvent & lastPoint,const TouchEvent & event)147 TouchLocationInfo TouchEventActuator::CreateChangedTouchInfo(const TouchEvent& lastPoint, const TouchEvent& event)
148 {
149 TouchLocationInfo changedInfo("onTouch", lastPoint.originalId);
150 PointF lastLocalPoint(lastPoint.x, lastPoint.y);
151 NGGestureRecognizer::Transform(lastLocalPoint, GetAttachedNode(), false, isPostEventResult_, event.postEventNodeId);
152 auto localX = static_cast<float>(lastLocalPoint.GetX());
153 auto localY = static_cast<float>(lastLocalPoint.GetY());
154 changedInfo.SetLocalLocation(Offset(localX, localY));
155 changedInfo.SetGlobalLocation(Offset(lastPoint.x, lastPoint.y));
156 changedInfo.SetScreenLocation(Offset(lastPoint.screenX, lastPoint.screenY));
157 changedInfo.SetTouchType(lastPoint.type);
158 changedInfo.SetForce(lastPoint.force);
159 changedInfo.SetPressedTime(lastPoint.pressedTime);
160 changedInfo.SetWidth(lastPoint.width);
161 changedInfo.SetHeight(lastPoint.height);
162 if (lastPoint.tiltX.has_value()) {
163 changedInfo.SetTiltX(lastPoint.tiltX.value());
164 }
165 if (lastPoint.tiltY.has_value()) {
166 changedInfo.SetTiltY(lastPoint.tiltY.value());
167 }
168 changedInfo.SetSourceTool(lastPoint.sourceTool);
169 changedInfo.SetOperatingHand(lastPoint.operatingHand);
170 return changedInfo;
171 }
172
CreateTouchItemInfo(const TouchPoint & pointItem,const TouchEvent & event,TouchType type)173 TouchLocationInfo TouchEventActuator::CreateTouchItemInfo(
174 const TouchPoint& pointItem, const TouchEvent& event, TouchType type)
175 {
176 float globalX = pointItem.x;
177 float globalY = pointItem.y;
178 float screenX = pointItem.screenX;
179 float screenY = pointItem.screenY;
180 PointF localPoint(globalX, globalY);
181 NGGestureRecognizer::Transform(localPoint, GetAttachedNode(), false, isPostEventResult_, event.postEventNodeId);
182 auto localX = static_cast<float>(localPoint.GetX());
183 auto localY = static_cast<float>(localPoint.GetY());
184 TouchLocationInfo info("onTouch", pointItem.originalId);
185 info.SetGlobalLocation(Offset(globalX, globalY));
186 info.SetLocalLocation(Offset(localX, localY));
187 info.SetScreenLocation(Offset(screenX, screenY));
188 info.SetTouchType(type);
189 info.SetForce(pointItem.force);
190 info.SetPressedTime(pointItem.downTime);
191 info.SetWidth(pointItem.width);
192 info.SetHeight(pointItem.height);
193 if (pointItem.tiltX.has_value()) {
194 info.SetTiltX(pointItem.tiltX.value());
195 }
196 if (pointItem.tiltY.has_value()) {
197 info.SetTiltY(pointItem.tiltY.value());
198 }
199 info.SetSourceTool(pointItem.sourceTool);
200 info.SetOperatingHand(pointItem.operatingHand);
201 return info;
202 }
203
CreateHistoryTouchItemInfo(const TouchEvent & eventItem,const TouchEvent & event)204 TouchLocationInfo TouchEventActuator::CreateHistoryTouchItemInfo(const TouchEvent& eventItem, const TouchEvent& event)
205 {
206 float globalX = eventItem.x;
207 float globalY = eventItem.y;
208 float screenX = eventItem.screenX;
209 float screenY = eventItem.screenY;
210 PointF localPoint(globalX, globalY);
211 NGGestureRecognizer::Transform(localPoint, GetAttachedNode(), false, isPostEventResult_, event.postEventNodeId);
212 auto localX = static_cast<float>(localPoint.GetX());
213 auto localY = static_cast<float>(localPoint.GetY());
214 TouchLocationInfo historyInfo("onTouch", eventItem.originalId);
215 historyInfo.SetTimeStamp(eventItem.time);
216 historyInfo.SetGlobalLocation(Offset(globalX, globalY));
217 historyInfo.SetLocalLocation(Offset(localX, localY));
218 historyInfo.SetScreenLocation(Offset(screenX, screenY));
219 historyInfo.SetTouchType(eventItem.type);
220 historyInfo.SetForce(eventItem.force);
221 historyInfo.SetPressedTime(eventItem.pressedTime);
222 historyInfo.SetWidth(eventItem.width);
223 historyInfo.SetHeight(eventItem.height);
224 if (eventItem.tiltX.has_value()) {
225 historyInfo.SetTiltX(eventItem.tiltX.value());
226 }
227 if (eventItem.tiltY.has_value()) {
228 historyInfo.SetTiltY(eventItem.tiltY.value());
229 }
230 historyInfo.SetSourceTool(eventItem.sourceTool);
231 return historyInfo;
232 }
233
TriggerCallBacks(TouchEventInfo & event)234 void TouchEventActuator::TriggerCallBacks(TouchEventInfo& event)
235 {
236 for (auto& impl : touchEvents_) {
237 if (impl) {
238 (*impl)(event);
239 }
240 }
241 if (userCallback_) {
242 // actuator->userCallback_ may be overwritten in its invoke so we copy it first
243 auto userCallback = userCallback_;
244 (*userCallback)(event);
245 }
246 if (touchAfterEvents_) {
247 auto touchAfterEvents = touchAfterEvents_;
248 (*touchAfterEvents)(event);
249 }
250 if (onTouchEventCallback_) {
251 // actuator->onTouchEventCallback_ may be overwritten in its invoke so we copy it first
252 auto onTouchEventCallback = onTouchEventCallback_;
253 (*onTouchEventCallback)(event);
254 }
255 if (commonTouchEventCallback_) {
256 // actuator->commonTouchEventCallback_ may be overwritten in its invoke so we copy it first
257 auto commonTouchEventCallback = commonTouchEventCallback_;
258 (*commonTouchEventCallback)(event);
259 }
260 }
261
262 } // namespace OHOS::Ace::NG