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 #include "render_touch_listener.h"
17
18 #include "core/components/touch_listener/touch_listener_component.h"
19 #include "core/event/ace_event_helper.h"
20
21 namespace OHOS::Ace {
22
RenderTouchListener()23 RenderTouchListener::RenderTouchListener() : rawRecognizer_(AceType::MakeRefPtr<RawRecognizer>()) {}
24
Create()25 RefPtr<RenderNode> RenderTouchListener::Create()
26 {
27 return AceType::MakeRefPtr<RenderTouchListener>();
28 }
29
Update(const RefPtr<Component> & component)30 void RenderTouchListener::Update(const RefPtr<Component>& component)
31 {
32 auto touchComponent = AceType::DynamicCast<TouchListenerComponent>(component);
33 ACE_DCHECK(touchComponent);
34 responseRegion_ = touchComponent->GetResponseRegion();
35 isResponseRegion_ = touchComponent->IsResponseRegion();
36 auto context = context_.Upgrade();
37 if (context && context->GetIsDeclarative()) {
38 onTouchEventCallback_ = AceSyncEvent<void(const std::shared_ptr<TouchEventInfo>&)>::Create(
39 touchComponent->GetOnTouchId(), context_);
40 return;
41 }
42
43 for (uint32_t eventStage = 0; eventStage < EventStage::SIZE; eventStage++) {
44 for (uint32_t touchEventType = 0; touchEventType < EventType::SIZE; touchEventType++) {
45 auto& onEventId = touchComponent->GetEvent(EventAction::ON, eventStage, touchEventType);
46 if (!onEventId.IsEmpty()) {
47 rawRecognizer_->SetOnEventCallback(
48 AceAsyncEvent<void(const TouchEventInfo&)>::Create(onEventId, context_), eventStage,
49 touchEventType);
50 }
51 auto& catchEventId = touchComponent->GetEvent(EventAction::CATCH, eventStage, touchEventType);
52 if (!catchEventId.IsEmpty()) {
53 rawRecognizer_->SetCatchEventCallback(
54 AceAsyncEvent<void()>::Create(catchEventId, context_), eventStage, touchEventType);
55 }
56 }
57
58 auto& onEventId = touchComponent->GetSwipeEvent(EventAction::ON, eventStage);
59 if (!onEventId.IsEmpty()) {
60 if (!swipeRecognizer_) {
61 swipeRecognizer_ = AceType::MakeRefPtr<SwipeRecognizer>();
62 }
63 swipeRecognizer_->SetSwipeCallback(
64 AceAsyncEvent<void(const SwipeEventInfo&)>::Create(onEventId, context_), eventStage);
65 }
66 auto& catchEventId = touchComponent->GetSwipeEvent(EventAction::CATCH, eventStage);
67 if (!catchEventId.IsEmpty()) {
68 if (!swipeRecognizer_) {
69 swipeRecognizer_ = AceType::MakeRefPtr<SwipeRecognizer>();
70 }
71 swipeRecognizer_->SetCatchEventCallback(
72 AceAsyncEvent<void(const SwipeEventInfo&)>::Create(catchEventId, context_), eventStage);
73 }
74 }
75 touchable_ = touchComponent->IsTouchable();
76 isVisible_ = touchComponent->IsVisible();
77 interceptTouchEvent_ = !touchable_;
78
79 if (!touchComponent->GetEvent(EventAction::CATCH, EventStage::CAPTURE, EventType::TOUCH_DOWN).IsEmpty()) {
80 EventMarker eventMarker("catchEvent");
81 auto event = AceAsyncEvent<void()>::Create(eventMarker, context_);
82 rawRecognizer_->SetCatchEventCallback(event, EventStage::CAPTURE, EventType::TOUCH_UP);
83 rawRecognizer_->SetCatchEventCallback(event, EventStage::CAPTURE, EventType::TOUCH_MOVE);
84 }
85 }
86
OnTouchTestHit(const Offset & coordinateOffset,const TouchRestrict & touchRestrict,TouchTestResult & result)87 void RenderTouchListener::OnTouchTestHit(
88 const Offset& coordinateOffset, const TouchRestrict& touchRestrict, TouchTestResult& result)
89 {
90 LOGD("render touch listener: on touch test hit!");
91 auto context = context_.Upgrade();
92 if (context && context->GetIsDeclarative()) {
93 coordinateOffset_ = coordinateOffset;
94 result.emplace_back(Claim(this));
95 return;
96 }
97 rawRecognizer_->SetCoordinateOffset(coordinateOffset);
98 result.emplace_back(rawRecognizer_);
99 if (swipeRecognizer_) {
100 result.emplace_back(swipeRecognizer_);
101 }
102 }
103
GetVisible() const104 bool RenderTouchListener::GetVisible() const
105 {
106 return RenderNode::GetVisible() && isVisible_;
107 }
108
DispatchEvent(const TouchEvent & point)109 bool RenderTouchListener::DispatchEvent(const TouchEvent& point)
110 {
111 return true;
112 }
113
HandleEvent(const TouchEvent & point)114 bool RenderTouchListener::HandleEvent(const TouchEvent& point)
115 {
116 bool isPropagation = true;
117 auto context = context_.Upgrade();
118 if (context && context->GetIsDeclarative()) {
119 if (point.type == TouchType::DOWN) {
120 touchPointMap_[point.id] = point;
121 isPropagation = TriggerTouchCallBack(point);
122 } else if (point.type == TouchType::UP) {
123 isPropagation = TriggerTouchCallBack(point);
124 touchPointMap_.erase(point.id);
125 } else {
126 for (const auto& pointPair : touchPointMap_) {
127 if (pointPair.first == point.id && (pointPair.second.x != point.x || pointPair.second.y != point.y)) {
128 touchPointMap_[point.id] = point;
129 isPropagation = TriggerTouchCallBack(point);
130 break;
131 }
132 }
133 }
134 }
135 return isPropagation;
136 }
137
TriggerTouchCallBack(const TouchEvent & changedPoint)138 bool RenderTouchListener::TriggerTouchCallBack(const TouchEvent& changedPoint)
139 {
140 LOGI("Trigger touch callback");
141 if (!onTouchEventCallback_ && !onTouchFocusEventCallback_) {
142 return true;
143 }
144 auto event = std::make_shared<TouchEventInfo>("touchEvent");
145 event->SetTimeStamp(changedPoint.time);
146 TouchLocationInfo changedInfo("onTouch", changedPoint.id);
147 float localX = changedPoint.x - coordinateOffset_.GetX();
148 float localY = changedPoint.y - coordinateOffset_.GetY();
149 changedInfo.SetLocalLocation(Offset(localX, localY));
150 changedInfo.SetGlobalLocation(Offset(changedPoint.x, changedPoint.y));
151 changedInfo.SetScreenLocation(Offset(changedPoint.screenX, changedPoint.screenY));
152 changedInfo.SetTouchType(changedPoint.type);
153 changedInfo.SetForce(changedPoint.force);
154 if (changedPoint.tiltX.has_value()) {
155 changedInfo.SetTiltX(changedPoint.tiltX.value());
156 }
157 if (changedPoint.tiltY.has_value()) {
158 changedInfo.SetTiltY(changedPoint.tiltY.value());
159 }
160 changedInfo.SetSourceTool(changedPoint.sourceTool);
161 event->AddChangedTouchLocationInfo(std::move(changedInfo));
162
163 // all fingers collection
164 for (const auto& pointPair : touchPointMap_) {
165 float globalX = pointPair.second.x;
166 float globalY = pointPair.second.y;
167 float screenX = pointPair.second.screenX;
168 float screenY = pointPair.second.screenY;
169 float localX = pointPair.second.x - coordinateOffset_.GetX();
170 float localY = pointPair.second.y - coordinateOffset_.GetY();
171 TouchLocationInfo info("onTouch", pointPair.second.id);
172 info.SetGlobalLocation(Offset(globalX, globalY));
173 info.SetLocalLocation(Offset(localX, localY));
174 info.SetScreenLocation(Offset(screenX, screenY));
175 info.SetTouchType(pointPair.second.type);
176 info.SetForce(pointPair.second.force);
177 if (pointPair.second.tiltX.has_value()) {
178 info.SetTiltX(pointPair.second.tiltX.value());
179 }
180 if (pointPair.second.tiltY.has_value()) {
181 info.SetTiltY(pointPair.second.tiltY.value());
182 }
183 info.SetSourceTool(pointPair.second.sourceTool);
184 event->AddTouchLocationInfo(std::move(info));
185 }
186 event->SetSourceDevice(changedPoint.sourceType);
187 event->SetForce(changedPoint.force);
188 if (changedPoint.tiltX.has_value()) {
189 event->SetTiltX(changedPoint.tiltX.value());
190 }
191 if (changedPoint.tiltY.has_value()) {
192 event->SetTiltY(changedPoint.tiltY.value());
193 }
194 event->SetSourceTool(changedPoint.sourceTool);
195 if (onTouchEventCallback_) {
196 onTouchEventCallback_(event);
197 }
198 if (onTouchFocusEventCallback_ && changedPoint.type == TouchType::DOWN) {
199 onTouchFocusEventCallback_();
200 }
201 LOGD("IsStopPropagation = %{public}d", event->IsStopPropagation());
202 return event->IsStopPropagation() ? false : true;
203 }
204
205 } // namespace OHOS::Ace