1 /*
2 * Copyright (c) 2022-2023 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/pattern/form/form_node.h"
17
18 #include "base/utils/utils.h"
19 #include "core/components/form/sub_container.h"
20 #include "core/components_ng/pattern/form/form_pattern.h"
21 #include "core/pipeline/pipeline_context.h"
22 #include "core/pipeline_ng/pipeline_context.h"
23 #include "pointer_event.h"
24
25 namespace OHOS::Ace::NG {
26 namespace {
27 const std::unordered_map<SourceType, int32_t> SOURCE_TYPE_MAP = {
28 { SourceType::TOUCH, MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN },
29 { SourceType::TOUCH_PAD, MMI::PointerEvent::SOURCE_TYPE_TOUCHPAD },
30 { SourceType::MOUSE, MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN },
31 };
32
33 const std::unordered_map<TouchType, int32_t> TOUCH_TYPE_MAP = {
34 { TouchType::CANCEL, MMI::PointerEvent::POINTER_ACTION_CANCEL },
35 { TouchType::DOWN, MMI::PointerEvent::POINTER_ACTION_DOWN },
36 { TouchType::MOVE, MMI::PointerEvent::POINTER_ACTION_MOVE },
37 { TouchType::UP, MMI::PointerEvent::POINTER_ACTION_UP },
38 { TouchType::PULL_DOWN, MMI::PointerEvent::POINTER_ACTION_PULL_DOWN },
39 { TouchType::PULL_MOVE, MMI::PointerEvent::POINTER_ACTION_PULL_MOVE },
40 { TouchType::PULL_UP, MMI::PointerEvent::POINTER_ACTION_PULL_UP },
41 { TouchType::PULL_IN_WINDOW, MMI::PointerEvent::POINTER_ACTION_PULL_IN_WINDOW },
42 { TouchType::PULL_OUT_WINDOW, MMI::PointerEvent::POINTER_ACTION_PULL_OUT_WINDOW },
43 };
44
ConvertPointerEvent(const OffsetF offsetF,const TouchEvent & point,const WeakPtr<FrameNode> & node)45 std::shared_ptr<MMI::PointerEvent> ConvertPointerEvent(const OffsetF offsetF, const TouchEvent& point,
46 const WeakPtr<FrameNode>& node)
47 {
48 std::shared_ptr<MMI::PointerEvent> pointerEvent = MMI::PointerEvent::Create();
49 if (pointerEvent == nullptr) {
50 TAG_LOGE(AceLogTag::ACE_FORM, "pointerEvent is nullptr");
51 return nullptr;
52 }
53 if (point.pointerEvent) {
54 pointerEvent->SetAxisValue(OHOS::MMI::PointerEvent::AxisType::AXIS_TYPE_SCROLL_HORIZONTAL,
55 point.pointerEvent->GetAxisValue(OHOS::MMI::PointerEvent::AxisType::AXIS_TYPE_SCROLL_HORIZONTAL));
56 pointerEvent->SetAxisValue(OHOS::MMI::PointerEvent::AxisType::AXIS_TYPE_SCROLL_VERTICAL,
57 point.pointerEvent->GetAxisValue(OHOS::MMI::PointerEvent::AxisType::AXIS_TYPE_SCROLL_VERTICAL));
58 pointerEvent->SetAxisValue(OHOS::MMI::PointerEvent::AxisType::AXIS_TYPE_PINCH,
59 point.pointerEvent->GetAxisValue(OHOS::MMI::PointerEvent::AxisType::AXIS_TYPE_PINCH));
60 pointerEvent->SetAxisValue(OHOS::MMI::PointerEvent::AxisType::AXIS_TYPE_ROTATE,
61 point.pointerEvent->GetAxisValue(OHOS::MMI::PointerEvent::AxisType::AXIS_TYPE_ROTATE));
62 }
63
64 OHOS::MMI::PointerEvent::PointerItem item;
65 PointF transformPoint(point.x, point.y);
66 NGGestureRecognizer::Transform(transformPoint, node);
67 item.SetWindowX(static_cast<int32_t>(transformPoint.GetX()));
68 item.SetWindowY(static_cast<int32_t>(transformPoint.GetY()));
69 item.SetWindowXPos(transformPoint.GetX());
70 item.SetWindowYPos(transformPoint.GetY());
71 item.SetDisplayX(static_cast<int32_t>(point.screenX));
72 item.SetDisplayY(static_cast<int32_t>(point.screenY));
73 item.SetPointerId(point.id);
74 pointerEvent->AddPointerItem(item);
75
76 int32_t sourceType = MMI::PointerEvent::SOURCE_TYPE_UNKNOWN;
77 auto sourceTypeIter = SOURCE_TYPE_MAP.find(point.sourceType);
78 if (sourceTypeIter != SOURCE_TYPE_MAP.end()) {
79 sourceType = sourceTypeIter->second;
80 }
81 pointerEvent->SetSourceType(sourceType);
82
83 int32_t pointerAction = OHOS::MMI::PointerEvent::POINTER_ACTION_UNKNOWN;
84 auto pointerActionIter = TOUCH_TYPE_MAP.find(point.type);
85 if (pointerActionIter != TOUCH_TYPE_MAP.end()) {
86 pointerAction = pointerActionIter->second;
87 }
88 pointerEvent->SetPointerAction(pointerAction);
89 pointerEvent->SetPointerId(point.id);
90 return pointerEvent;
91 }
92
ConvertPointerEvent(const OffsetF offsetF,const AxisEvent & point,const WeakPtr<FrameNode> & node)93 std::shared_ptr<MMI::PointerEvent> ConvertPointerEvent(const OffsetF offsetF, const AxisEvent& point,
94 const WeakPtr<FrameNode>& node)
95 {
96 std::shared_ptr<MMI::PointerEvent> pointerEvent = MMI::PointerEvent::Create();
97 if (pointerEvent == nullptr) {
98 TAG_LOGE(AceLogTag::ACE_FORM, "pointerEvent is nullptr");
99 return nullptr;
100 }
101
102 pointerEvent->SetAxisValue(OHOS::MMI::PointerEvent::AxisType::AXIS_TYPE_SCROLL_HORIZONTAL, point.horizontalAxis);
103 pointerEvent->SetAxisValue(OHOS::MMI::PointerEvent::AxisType::AXIS_TYPE_SCROLL_VERTICAL, point.verticalAxis);
104 pointerEvent->SetAxisValue(OHOS::MMI::PointerEvent::AxisType::AXIS_TYPE_PINCH, point.pinchAxisScale);
105 pointerEvent->SetAxisValue(OHOS::MMI::PointerEvent::AxisType::AXIS_TYPE_ROTATE, point.rotateAxisAngle);
106
107 OHOS::MMI::PointerEvent::PointerItem item;
108 PointF transformPoint(point.x, point.y);
109 NGGestureRecognizer::Transform(transformPoint, node);
110 item.SetWindowX(static_cast<int32_t>(transformPoint.GetX()));
111 item.SetWindowY(static_cast<int32_t>(transformPoint.GetY()));
112 item.SetWindowXPos(transformPoint.GetX());
113 item.SetWindowYPos(transformPoint.GetY());
114 item.SetDisplayX(static_cast<int32_t>(point.screenX));
115 item.SetDisplayY(static_cast<int32_t>(point.screenY));
116 item.SetPointerId(point.id);
117 MMI::PointerEvent::PointerItem pointerItem;
118 bool ret = point.pointerEvent->GetPointerItem(point.id, pointerItem);
119 if (!ret) {
120 LOGE("get pointer: %{public}d item failed.", point.id);
121 return nullptr;
122 }
123 item.SetToolType(pointerItem.GetToolType());
124 item.SetOriginPointerId(point.originalId);
125 pointerEvent->AddPointerItem(item);
126 pointerEvent->SetSourceType(point.pointerEvent->GetSourceType());
127 pointerEvent->SetPointerAction(point.pointerEvent->GetPointerAction());
128 pointerEvent->SetPointerId(point.id);
129 pointerEvent->SetDeviceId(static_cast<int32_t>(point.deviceId));
130 pointerEvent->SetId(point.touchEventId);
131 pointerEvent->SetTargetDisplayId(point.targetDisplayId);
132 return pointerEvent;
133 }
134
135 class FormAccessibilityChildTreeCallback : public AccessibilityChildTreeCallback {
136 public:
FormAccessibilityChildTreeCallback(const WeakPtr<FormNode> & weakFormNode,int64_t accessibilityId)137 FormAccessibilityChildTreeCallback(const WeakPtr<FormNode> &weakFormNode, int64_t accessibilityId)
138 : AccessibilityChildTreeCallback(accessibilityId), weakFormNode_(weakFormNode)
139 {}
140
141 ~FormAccessibilityChildTreeCallback() override = default;
142
OnRegister(uint32_t windowId,int32_t treeId)143 bool OnRegister(uint32_t windowId, int32_t treeId) override
144 {
145 auto formNode = weakFormNode_.Upgrade();
146 if (formNode == nullptr) {
147 return false;
148 }
149 if (isReg_) {
150 return true;
151 }
152 formNode->OnAccessibilityChildTreeRegister(windowId, treeId);
153 isReg_ = true;
154 return true;
155 }
156
OnDeregister()157 bool OnDeregister() override
158 {
159 auto formNode = weakFormNode_.Upgrade();
160 if (formNode == nullptr) {
161 return false;
162 }
163 if (!isReg_) {
164 return true;
165 }
166 formNode->OnAccessibilityChildTreeDeregister();
167 isReg_ = false;
168 return true;
169 }
170
OnSetChildTree(int32_t childWindowId,int32_t childTreeId)171 bool OnSetChildTree(int32_t childWindowId, int32_t childTreeId) override
172 {
173 auto formNode = weakFormNode_.Upgrade();
174 if (formNode == nullptr) {
175 return false;
176 }
177 formNode->OnSetAccessibilityChildTree(childWindowId, childTreeId);
178 return true;
179 }
180
OnDumpChildInfo(const std::vector<std::string> & params,std::vector<std::string> & info)181 bool OnDumpChildInfo(const std::vector<std::string>& params, std::vector<std::string>& info) override
182 {
183 auto formNode = weakFormNode_.Upgrade();
184 if (formNode == nullptr) {
185 return false;
186 }
187 formNode->OnAccessibilityDumpChildInfo(params, info);
188 return true;
189 }
190
OnClearRegisterFlag()191 void OnClearRegisterFlag() override
192 {
193 auto formNode = weakFormNode_.Upgrade();
194 if (formNode == nullptr) {
195 return;
196 }
197 isReg_ = false;
198 }
199 private:
200 bool isReg_ = false;
201 WeakPtr<FormNode> weakFormNode_;
202 };
203 }
204
~FormNode()205 FormNode::~FormNode()
206 {
207 auto pipeline = PipelineContext::GetCurrentContext();
208 CHECK_NULL_VOID(pipeline);
209 auto accessibilityManager = pipeline->GetAccessibilityManager();
210 CHECK_NULL_VOID(accessibilityManager);
211 accessibilityManager->DeregisterAccessibilityChildTreeCallback(GetAccessibilityId());
212 }
213
AxisTest(const PointF & globalPoint,const PointF & parentLocalPoint,const PointF & parentRevertPoint,TouchRestrict & touchRestrict,AxisTestResult & axisResult)214 HitTestResult FormNode::AxisTest(const PointF& globalPoint, const PointF& parentLocalPoint,
215 const PointF& parentRevertPoint, TouchRestrict& touchRestrict, AxisTestResult& axisResult)
216 {
217 auto testResult = FrameNode::AxisTest(globalPoint, parentLocalPoint, parentRevertPoint, touchRestrict, axisResult);
218 if (testResult == HitTestResult::OUT_OF_REGION) {
219 return HitTestResult::OUT_OF_REGION;
220 }
221
222 auto context = GetContext();
223 CHECK_NULL_RETURN(context, testResult);
224 auto pattern = GetPattern<FormPattern>();
225 CHECK_NULL_RETURN(pattern, testResult);
226 auto subContainer = pattern->GetSubContainer();
227 CHECK_NULL_RETURN(subContainer, testResult);
228
229 // Send AxisEvent to FormRenderService when Provider is ArkTS Card.
230 if (subContainer->GetUISyntaxType() == FrontendType::ETS_CARD) {
231 auto callback = [weak = WeakClaim(this)](const AxisEvent& axisEvent, SerializedGesture& serializedGesture) {
232 auto formNode = weak.Upgrade();
233 CHECK_NULL_VOID(formNode);
234 formNode->DispatchPointerEvent(axisEvent, serializedGesture);
235 };
236 auto mgr = context->GetFormEventManager();
237 if (mgr) {
238 mgr->AddEtsCardAxisEventCallback(touchRestrict.touchEvent.id, callback);
239 }
240 return testResult;
241 }
242 return testResult;
243 }
244
TouchTest(const PointF & globalPoint,const PointF & parentLocalPoint,const PointF & parentRevertPoint,TouchRestrict & touchRestrict,TouchTestResult & result,int32_t touchId,ResponseLinkResult & responseLinkResult,bool isDispatch)245 HitTestResult FormNode::TouchTest(const PointF& globalPoint, const PointF& parentLocalPoint,
246 const PointF& parentRevertPoint, TouchRestrict& touchRestrict, TouchTestResult& result, int32_t touchId,
247 ResponseLinkResult& responseLinkResult, bool isDispatch)
248 {
249 // The mousetest has been merged into touchtest.
250 // FormComponent does not support some mouse event(eg. Hover, HoverAnimation..).
251 // Mouse event like LEFT_BUTTON, RELEASE use touchevent to dispatch, so they work well on FormComponent
252 if (touchRestrict.hitTestType == SourceType::MOUSE) {
253 return HitTestResult::OUT_OF_REGION;
254 }
255
256 auto testResult = FrameNode::TouchTest(
257 globalPoint, parentLocalPoint, parentRevertPoint, touchRestrict, result, touchId, responseLinkResult);
258 if (testResult == HitTestResult::OUT_OF_REGION) {
259 return HitTestResult::OUT_OF_REGION;
260 }
261
262 auto context = GetContext();
263 CHECK_NULL_RETURN(context, testResult);
264
265 auto selfGlobalOffset = GetTransformRelativeOffset();
266 auto pattern = GetPattern<FormPattern>();
267 CHECK_NULL_RETURN(pattern, testResult);
268 auto subContainer = pattern->GetSubContainer();
269 CHECK_NULL_RETURN(subContainer, testResult);
270
271 // Send TouchEvent Info to FormRenderService when Provider is ArkTS Card.
272 if (subContainer->GetUISyntaxType() == FrontendType::ETS_CARD) {
273 auto callback = [weak = WeakClaim(this)](const TouchEvent& touchEvent, SerializedGesture& serializedGesture) {
274 auto formNode = weak.Upgrade();
275 CHECK_NULL_VOID(formNode);
276 formNode->DispatchPointerEvent(touchEvent, serializedGesture);
277 };
278 auto mgr = context->GetFormEventManager();
279 if (mgr) {
280 mgr->AddEtsCardTouchEventCallback(touchRestrict.touchEvent.id, callback);
281 }
282 return testResult;
283 }
284 auto subContext = DynamicCast<OHOS::Ace::PipelineBase>(subContainer->GetPipelineContext());
285 CHECK_NULL_RETURN(subContext, testResult);
286 subContext->SetPluginEventOffset(Offset(selfGlobalOffset.GetX(), selfGlobalOffset.GetY()));
287 context->SetTouchPipeline(WeakPtr<PipelineBase>(subContext));
288
289 return testResult;
290 }
291
DispatchPointerEvent(const TouchEvent & touchEvent,SerializedGesture & serializedGesture)292 void FormNode::DispatchPointerEvent(const TouchEvent& touchEvent,
293 SerializedGesture& serializedGesture)
294 {
295 auto pattern = GetPattern<FormPattern>();
296 CHECK_NULL_VOID(pattern);
297 auto selfGlobalOffset = GetFormOffset();
298 auto pointerEvent = ConvertPointerEvent(selfGlobalOffset, touchEvent, WeakClaim(this));
299 pattern->DispatchPointerEvent(pointerEvent, serializedGesture);
300 }
301
DispatchPointerEvent(const AxisEvent & axisEvent,SerializedGesture & serializedGesture)302 void FormNode::DispatchPointerEvent(const AxisEvent& axisEvent,
303 SerializedGesture& serializedGesture)
304 {
305 auto pattern = GetPattern<FormPattern>();
306 CHECK_NULL_VOID(pattern);
307
308 auto selfGlobalOffset = GetFormOffset();
309 auto pointerEvent = ConvertPointerEvent(selfGlobalOffset, axisEvent, WeakClaim(this));
310 pattern->DispatchPointerEvent(pointerEvent, serializedGesture);
311 }
312
GetFormOffset() const313 OffsetF FormNode::GetFormOffset() const
314 {
315 auto context = GetRenderContext();
316 CHECK_NULL_RETURN(context, OffsetF());
317 auto offset = context->GetPaintRectWithoutTransform().GetOffset();
318 auto parent = GetAncestorNodeOfFrame(true);
319
320 while (parent) {
321 auto parentRenderContext = parent->GetRenderContext();
322 offset += parentRenderContext->GetPaintRectWithTransform().GetOffset();
323 parent = parent->GetAncestorNodeOfFrame(true);
324 }
325
326 return offset;
327 }
328
GetOrCreateFormNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)329 RefPtr<FormNode> FormNode::GetOrCreateFormNode(
330 const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
331 {
332 auto formNode = ElementRegister::GetInstance()->GetSpecificItemById<FormNode>(nodeId);
333 if (formNode) {
334 if (formNode->GetTag() == tag) {
335 return formNode;
336 }
337 ElementRegister::GetInstance()->RemoveItemSilently(nodeId);
338 auto parent = formNode->GetParent();
339 if (parent) {
340 parent->RemoveChild(formNode);
341 }
342 }
343
344 auto pattern = patternCreator ? patternCreator() : AceType::MakeRefPtr<Pattern>();
345 formNode = AceType::MakeRefPtr<FormNode>(tag, nodeId, pattern, false);
346 formNode->InitializePatternAndContext();
347 formNode->InitializeFormAccessibility();
348 ElementRegister::GetInstance()->AddUINode(formNode);
349 return formNode;
350 }
351
OnDetachFromMainTree(bool recursive,PipelineContext * context)352 void FormNode::OnDetachFromMainTree(bool recursive, PipelineContext* context)
353 {
354 auto eventHub = GetOrCreateEventHub<FormEventHub>();
355 eventHub->FireOnCache();
356 FrameNode::OnDetachFromMainTree(recursive, context);
357 }
358
InitializeFormAccessibility()359 void FormNode::InitializeFormAccessibility()
360 {
361 auto pipeline = PipelineContext::GetCurrentContext();
362 CHECK_NULL_VOID(pipeline);
363 auto accessibilityManager = pipeline->GetAccessibilityManager();
364 CHECK_NULL_VOID(accessibilityManager);
365 accessibilityChildTreeCallback_ = std::make_shared<FormAccessibilityChildTreeCallback>(
366 WeakClaim(this), GetAccessibilityId());
367 accessibilityManager->RegisterAccessibilityChildTreeCallback(GetAccessibilityId(), accessibilityChildTreeCallback_);
368
369 }
370
NotifyAccessibilityChildTreeRegister()371 void FormNode::NotifyAccessibilityChildTreeRegister()
372 {
373 auto pipeline = PipelineContext::GetCurrentContext();
374 CHECK_NULL_VOID(pipeline);
375 auto accessibilityManager = pipeline->GetAccessibilityManager();
376 CHECK_NULL_VOID(accessibilityManager);
377 if (accessibilityManager->IsRegister()) {
378 accessibilityChildTreeCallback_->OnRegister(pipeline->GetWindowId(), 0);
379 }
380 }
381
OnAccessibilityChildTreeRegister(uint32_t windowId,int32_t treeId)382 void FormNode::OnAccessibilityChildTreeRegister(uint32_t windowId, int32_t treeId)
383 {
384 auto accessibilityId = GetAccessibilityId();
385 auto pattern = GetPattern<FormPattern>();
386 if (pattern == nullptr) {
387 TAG_LOGE(AceLogTag::ACE_FORM, "pattern is null");
388 return;
389 }
390 pattern->OnAccessibilityChildTreeRegister(windowId, treeId, accessibilityId);
391 }
392
OnAccessibilityChildTreeDeregister()393 void FormNode::OnAccessibilityChildTreeDeregister()
394 {
395 auto pattern = GetPattern<FormPattern>();
396 CHECK_NULL_VOID(pattern);
397 pattern->OnAccessibilityChildTreeDeregister();
398 }
399
OnSetAccessibilityChildTree(int32_t childWindowId,int32_t childTreeId)400 void FormNode::OnSetAccessibilityChildTree(int32_t childWindowId, int32_t childTreeId)
401 {
402 auto accessibilityProperty = GetAccessibilityProperty<AccessibilityProperty>();
403 if (accessibilityProperty != nullptr) {
404 accessibilityProperty->SetChildWindowId(childWindowId);
405 accessibilityProperty->SetChildTreeId(childTreeId);
406 }
407 }
408
OnAccessibilityDumpChildInfo(const std::vector<std::string> & params,std::vector<std::string> & info)409 void FormNode::OnAccessibilityDumpChildInfo(const std::vector<std::string>& params, std::vector<std::string>& info)
410 {
411 auto pattern = GetPattern<FormPattern>();
412 if (pattern == nullptr) {
413 TAG_LOGE(AceLogTag::ACE_FORM, "pattern is null");
414 return;
415 }
416 pattern->OnAccessibilityDumpChildInfo(params, info);
417 }
418
ClearAccessibilityChildTreeRegisterFlag()419 void FormNode::ClearAccessibilityChildTreeRegisterFlag()
420 {
421 CHECK_NULL_VOID(accessibilityChildTreeCallback_);
422 accessibilityChildTreeCallback_->OnClearRegisterFlag();
423 }
424
GetImageId()425 int32_t FormNode::GetImageId()
426 {
427 if (!imageId_.has_value()) {
428 imageId_ = ElementRegister::GetInstance()->MakeUniqueId();
429 }
430 return imageId_.value();
431 }
432 } // namespace OHOS::Ace::NG
433