• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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