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/log/log.h"
19 #include "base/utils/utils.h"
20 #include "core/components/form/sub_container.h"
21 #include "core/components_ng/pattern/form/form_pattern.h"
22 #include "core/pipeline/pipeline_context.h"
23 #include "core/pipeline_ng/pipeline_context.h"
24 #include "pointer_event.h"
25
26 namespace OHOS::Ace::NG {
27 namespace {
28 const std::unordered_map<SourceType, int32_t> SOURCE_TYPE_MAP = {
29 { SourceType::TOUCH, MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN },
30 { SourceType::TOUCH_PAD, MMI::PointerEvent::SOURCE_TYPE_TOUCHPAD },
31 { SourceType::MOUSE, MMI::PointerEvent::SOURCE_TYPE_TOUCHSCREEN },
32 };
33
34 const std::unordered_map<TouchType, int32_t> TOUCH_TYPE_MAP = {
35 { TouchType::CANCEL, MMI::PointerEvent::POINTER_ACTION_CANCEL },
36 { TouchType::DOWN, MMI::PointerEvent::POINTER_ACTION_DOWN },
37 { TouchType::MOVE, MMI::PointerEvent::POINTER_ACTION_MOVE },
38 { TouchType::UP, MMI::PointerEvent::POINTER_ACTION_UP },
39 { TouchType::PULL_DOWN, MMI::PointerEvent::POINTER_ACTION_PULL_DOWN },
40 { TouchType::PULL_MOVE, MMI::PointerEvent::POINTER_ACTION_PULL_MOVE },
41 { TouchType::PULL_UP, MMI::PointerEvent::POINTER_ACTION_PULL_UP },
42 { TouchType::PULL_IN_WINDOW, MMI::PointerEvent::POINTER_ACTION_PULL_IN_WINDOW },
43 { TouchType::PULL_OUT_WINDOW, MMI::PointerEvent::POINTER_ACTION_PULL_OUT_WINDOW },
44 };
45
ConvertPointerEvent(const OffsetF offsetF,const TouchEvent & point,const WeakPtr<FrameNode> & node)46 std::shared_ptr<MMI::PointerEvent> ConvertPointerEvent(const OffsetF offsetF, const TouchEvent& point,
47 const WeakPtr<FrameNode>& node)
48 {
49 std::shared_ptr<MMI::PointerEvent> pointerEvent = MMI::PointerEvent::Create();
50 if (pointerEvent == nullptr) {
51 TAG_LOGE(AceLogTag::ACE_FORM, "pointerEvent is nullptr");
52 return nullptr;
53 }
54
55 OHOS::MMI::PointerEvent::PointerItem item;
56 PointF transformPoint(point.x, point.y);
57 NGGestureRecognizer::Transform(transformPoint, node);
58 item.SetWindowX(static_cast<int32_t>(transformPoint.GetX()));
59 item.SetWindowY(static_cast<int32_t>(transformPoint.GetY()));
60 item.SetWindowXPos(transformPoint.GetX());
61 item.SetWindowYPos(transformPoint.GetY());
62 item.SetDisplayX(static_cast<int32_t>(point.screenX));
63 item.SetDisplayY(static_cast<int32_t>(point.screenY));
64 item.SetPointerId(point.id);
65 pointerEvent->AddPointerItem(item);
66
67 int32_t sourceType = MMI::PointerEvent::SOURCE_TYPE_UNKNOWN;
68 auto sourceTypeIter = SOURCE_TYPE_MAP.find(point.sourceType);
69 if (sourceTypeIter != SOURCE_TYPE_MAP.end()) {
70 sourceType = sourceTypeIter->second;
71 }
72 pointerEvent->SetSourceType(sourceType);
73
74 int32_t pointerAction = OHOS::MMI::PointerEvent::POINTER_ACTION_UNKNOWN;
75 auto pointerActionIter = TOUCH_TYPE_MAP.find(point.type);
76 if (pointerActionIter != TOUCH_TYPE_MAP.end()) {
77 pointerAction = pointerActionIter->second;
78 }
79 pointerEvent->SetPointerAction(pointerAction);
80 pointerEvent->SetPointerId(point.id);
81 return pointerEvent;
82 }
83
84 class FormAccessibilityChildTreeCallback : public AccessibilityChildTreeCallback {
85 public:
FormAccessibilityChildTreeCallback(const WeakPtr<FormNode> & weakFormNode,int64_t accessibilityId)86 FormAccessibilityChildTreeCallback(const WeakPtr<FormNode> &weakFormNode, int64_t accessibilityId)
87 : AccessibilityChildTreeCallback(accessibilityId), weakFormNode_(weakFormNode)
88 {}
89
90 ~FormAccessibilityChildTreeCallback() override = default;
91
OnRegister(uint32_t windowId,int32_t treeId)92 bool OnRegister(uint32_t windowId, int32_t treeId) override
93 {
94 auto formNode = weakFormNode_.Upgrade();
95 if (formNode == nullptr) {
96 return false;
97 }
98 if (isReg_) {
99 return true;
100 }
101 formNode->OnAccessibilityChildTreeRegister(windowId, treeId);
102 isReg_ = true;
103 return true;
104 }
105
OnDeregister()106 bool OnDeregister() override
107 {
108 auto formNode = weakFormNode_.Upgrade();
109 if (formNode == nullptr) {
110 return false;
111 }
112 if (!isReg_) {
113 return true;
114 }
115 formNode->OnAccessibilityChildTreeDeregister();
116 isReg_ = false;
117 return true;
118 }
119
OnSetChildTree(int32_t childWindowId,int32_t childTreeId)120 bool OnSetChildTree(int32_t childWindowId, int32_t childTreeId) override
121 {
122 auto formNode = weakFormNode_.Upgrade();
123 if (formNode == nullptr) {
124 return false;
125 }
126 formNode->OnSetAccessibilityChildTree(childWindowId, childTreeId);
127 return true;
128 }
129
OnDumpChildInfo(const std::vector<std::string> & params,std::vector<std::string> & info)130 bool OnDumpChildInfo(const std::vector<std::string>& params, std::vector<std::string>& info) override
131 {
132 auto formNode = weakFormNode_.Upgrade();
133 if (formNode == nullptr) {
134 return false;
135 }
136 formNode->OnAccessibilityDumpChildInfo(params, info);
137 return true;
138 }
139
OnClearRegisterFlag()140 void OnClearRegisterFlag() override
141 {
142 auto formNode = weakFormNode_.Upgrade();
143 if (formNode == nullptr) {
144 return;
145 }
146 isReg_ = false;
147 }
148 private:
149 bool isReg_ = false;
150 WeakPtr<FormNode> weakFormNode_;
151 };
152 }
153
~FormNode()154 FormNode::~FormNode()
155 {
156 auto pipeline = PipelineContext::GetCurrentContext();
157 CHECK_NULL_VOID(pipeline);
158 auto accessibilityManager = pipeline->GetAccessibilityManager();
159 CHECK_NULL_VOID(accessibilityManager);
160 accessibilityManager->DeregisterAccessibilityChildTreeCallback(GetAccessibilityId());
161 }
162
TouchTest(const PointF & globalPoint,const PointF & parentLocalPoint,const PointF & parentRevertPoint,TouchRestrict & touchRestrict,TouchTestResult & result,int32_t touchId,ResponseLinkResult & responseLinkResult,bool isDispatch)163 HitTestResult FormNode::TouchTest(const PointF& globalPoint, const PointF& parentLocalPoint,
164 const PointF& parentRevertPoint, TouchRestrict& touchRestrict, TouchTestResult& result, int32_t touchId,
165 ResponseLinkResult& responseLinkResult, bool isDispatch)
166 {
167 // The mousetest has been merged into touchtest.
168 // FormComponent does not support some mouse event(eg. Hover, HoverAnimation..).
169 // Mouse event like LEFT_BUTTON, RELEASE use touchevent to dispatch, so they work well on FormComponent
170 if (touchRestrict.hitTestType == SourceType::MOUSE) {
171 return HitTestResult::OUT_OF_REGION;
172 }
173
174 auto testResult = FrameNode::TouchTest(
175 globalPoint, parentLocalPoint, parentRevertPoint, touchRestrict, result, touchId, responseLinkResult);
176 if (testResult == HitTestResult::OUT_OF_REGION) {
177 return HitTestResult::OUT_OF_REGION;
178 }
179
180 auto context = GetContext();
181 CHECK_NULL_RETURN(context, testResult);
182
183 auto selfGlobalOffset = GetTransformRelativeOffset();
184 auto pattern = GetPattern<FormPattern>();
185 CHECK_NULL_RETURN(pattern, testResult);
186 auto subContainer = pattern->GetSubContainer();
187 CHECK_NULL_RETURN(subContainer, testResult);
188
189 // Send TouchEvent Info to FormRenderService when Provider is ArkTS Card.
190 if (subContainer->GetUISyntaxType() == FrontendType::ETS_CARD) {
191 auto callback = [weak = WeakClaim(this)](const TouchEvent& touchEvent, SerializedGesture& serializedGesture) {
192 auto formNode = weak.Upgrade();
193 CHECK_NULL_VOID(formNode);
194 formNode->DispatchPointerEvent(touchEvent, serializedGesture);
195 };
196 context->AddEtsCardTouchEventCallback(touchRestrict.touchEvent.id, callback);
197 return testResult;
198 }
199 auto subContext = DynamicCast<OHOS::Ace::PipelineBase>(subContainer->GetPipelineContext());
200 CHECK_NULL_RETURN(subContext, testResult);
201 subContext->SetPluginEventOffset(Offset(selfGlobalOffset.GetX(), selfGlobalOffset.GetY()));
202 context->SetTouchPipeline(WeakPtr<PipelineBase>(subContext));
203
204 return testResult;
205 }
206
DispatchPointerEvent(const TouchEvent & touchEvent,SerializedGesture & serializedGesture)207 void FormNode::DispatchPointerEvent(const TouchEvent& touchEvent,
208 SerializedGesture& serializedGesture)
209 {
210 auto pattern = GetPattern<FormPattern>();
211 CHECK_NULL_VOID(pattern);
212 auto selfGlobalOffset = GetFormOffset();
213 auto pointerEvent = ConvertPointerEvent(selfGlobalOffset, touchEvent, WeakClaim(this));
214 pattern->DispatchPointerEvent(pointerEvent, serializedGesture);
215 }
216
GetFormOffset() const217 OffsetF FormNode::GetFormOffset() const
218 {
219 auto context = GetRenderContext();
220 CHECK_NULL_RETURN(context, OffsetF());
221 auto offset = context->GetPaintRectWithoutTransform().GetOffset();
222 auto parent = GetAncestorNodeOfFrame();
223
224 while (parent) {
225 auto parentRenderContext = parent->GetRenderContext();
226 offset += parentRenderContext->GetPaintRectWithTransform().GetOffset();
227 parent = parent->GetAncestorNodeOfFrame();
228 }
229
230 return offset;
231 }
232
GetOrCreateFormNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)233 RefPtr<FormNode> FormNode::GetOrCreateFormNode(
234 const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
235 {
236 auto formNode = ElementRegister::GetInstance()->GetSpecificItemById<FormNode>(nodeId);
237 if (formNode) {
238 if (formNode->GetTag() == tag) {
239 return formNode;
240 }
241 ElementRegister::GetInstance()->RemoveItemSilently(nodeId);
242 auto parent = formNode->GetParent();
243 if (parent) {
244 parent->RemoveChild(formNode);
245 }
246 }
247
248 auto pattern = patternCreator ? patternCreator() : AceType::MakeRefPtr<Pattern>();
249 formNode = AceType::MakeRefPtr<FormNode>(tag, nodeId, pattern, false);
250 formNode->InitializePatternAndContext();
251 formNode->InitializeFormAccessibility();
252 ElementRegister::GetInstance()->AddUINode(formNode);
253 return formNode;
254 }
255
OnDetachFromMainTree(bool recursive,PipelineContext * context)256 void FormNode::OnDetachFromMainTree(bool recursive, PipelineContext* context)
257 {
258 auto eventHub = GetEventHub<FormEventHub>();
259 eventHub->FireOnCache();
260 FrameNode::OnDetachFromMainTree(recursive, context);
261 }
262
InitializeFormAccessibility()263 void FormNode::InitializeFormAccessibility()
264 {
265 auto pipeline = PipelineContext::GetCurrentContext();
266 CHECK_NULL_VOID(pipeline);
267 auto accessibilityManager = pipeline->GetAccessibilityManager();
268 CHECK_NULL_VOID(accessibilityManager);
269 accessibilityChildTreeCallback_ = std::make_shared<FormAccessibilityChildTreeCallback>(
270 WeakClaim(this), GetAccessibilityId());
271 accessibilityManager->RegisterAccessibilityChildTreeCallback(GetAccessibilityId(), accessibilityChildTreeCallback_);
272
273 }
274
NotifyAccessibilityChildTreeRegister()275 void FormNode::NotifyAccessibilityChildTreeRegister()
276 {
277 auto pipeline = PipelineContext::GetCurrentContext();
278 CHECK_NULL_VOID(pipeline);
279 auto accessibilityManager = pipeline->GetAccessibilityManager();
280 CHECK_NULL_VOID(accessibilityManager);
281 if (accessibilityManager->IsRegister()) {
282 accessibilityChildTreeCallback_->OnRegister(pipeline->GetWindowId(), 0);
283 }
284 }
285
OnAccessibilityChildTreeRegister(uint32_t windowId,int32_t treeId)286 void FormNode::OnAccessibilityChildTreeRegister(uint32_t windowId, int32_t treeId)
287 {
288 auto accessibilityId = GetAccessibilityId();
289 auto pattern = GetPattern<FormPattern>();
290 if (pattern == nullptr) {
291 TAG_LOGE(AceLogTag::ACE_FORM, "pattern is null");
292 return;
293 }
294 pattern->OnAccessibilityChildTreeRegister(windowId, treeId, accessibilityId);
295 }
296
OnAccessibilityChildTreeDeregister()297 void FormNode::OnAccessibilityChildTreeDeregister()
298 {
299 auto pattern = GetPattern<FormPattern>();
300 CHECK_NULL_VOID(pattern);
301 pattern->OnAccessibilityChildTreeDeregister();
302 }
303
OnSetAccessibilityChildTree(int32_t childWindowId,int32_t childTreeId)304 void FormNode::OnSetAccessibilityChildTree(int32_t childWindowId, int32_t childTreeId)
305 {
306 auto accessibilityProperty = GetAccessibilityProperty<AccessibilityProperty>();
307 if (accessibilityProperty != nullptr) {
308 accessibilityProperty->SetChildWindowId(childWindowId);
309 accessibilityProperty->SetChildTreeId(childTreeId);
310 }
311 }
312
OnAccessibilityDumpChildInfo(const std::vector<std::string> & params,std::vector<std::string> & info)313 void FormNode::OnAccessibilityDumpChildInfo(const std::vector<std::string>& params, std::vector<std::string>& info)
314 {
315 auto pattern = GetPattern<FormPattern>();
316 if (pattern == nullptr) {
317 TAG_LOGE(AceLogTag::ACE_FORM, "pattern is null");
318 return;
319 }
320 pattern->OnAccessibilityDumpChildInfo(params, info);
321 }
322
ClearAccessibilityChildTreeRegisterFlag()323 void FormNode::ClearAccessibilityChildTreeRegisterFlag()
324 {
325 CHECK_NULL_VOID(accessibilityChildTreeCallback_);
326 accessibilityChildTreeCallback_->OnClearRegisterFlag();
327 }
328 } // namespace OHOS::Ace::NG
329