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/base/frame_node.h"
17
18 #include "base/geometry/ng/point_t.h"
19 #include "base/log/ace_trace.h"
20 #include "base/log/dump_log.h"
21 #include "base/memory/ace_type.h"
22 #include "base/memory/referenced.h"
23 #include "base/thread/cancelable_callback.h"
24 #include "base/thread/task_executor.h"
25 #include "base/utils/system_properties.h"
26 #include "base/utils/utils.h"
27 #include "core/common/ace_application_info.h"
28 #include "core/components/common/layout/constants.h"
29 #include "core/components_ng/base/ui_node.h"
30 #include "core/components_ng/event/gesture_event_hub.h"
31 #include "core/components_ng/layout/layout_algorithm.h"
32 #include "core/components_ng/layout/layout_wrapper.h"
33 #include "core/components_ng/pattern/pattern.h"
34 #include "core/components_ng/property/measure_property.h"
35 #include "core/components_ng/property/measure_utils.h"
36 #include "core/components_ng/property/property.h"
37 #include "core/components_ng/render/paint_wrapper.h"
38 #include "core/components_v2/inspector/inspector_constants.h"
39 #include "core/pipeline_ng/pipeline_context.h"
40 #include "core/pipeline_ng/ui_task_scheduler.h"
41
42 namespace {
43 constexpr double VISIBLE_RATIO_MIN = 0.0;
44 constexpr double VISIBLE_RATIO_MAX = 1.0;
45 #if defined(PREVIEW)
46 constexpr int32_t SUBSTR_LENGTH = 3;
47 const char DIMENSION_UNIT_VP[] = "vp";
48 #endif
49 } // namespace
50 namespace OHOS::Ace::NG {
FrameNode(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern,bool isRoot)51 FrameNode::FrameNode(const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern, bool isRoot)
52 : UINode(tag, nodeId, isRoot), pattern_(pattern)
53 {
54 renderContext_->InitContext(IsRootNode(), pattern_->GetSurfaceNodeName(), pattern_->UseExternalRSNode());
55 paintProperty_ = pattern->CreatePaintProperty();
56 layoutProperty_ = pattern->CreateLayoutProperty();
57 eventHub_ = pattern->CreateEventHub();
58 accessibilityProperty_ = pattern->CreateAccessibilityProperty();
59 // first create make layout property dirty.
60 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
61 layoutProperty_->SetHost(WeakClaim(this));
62 }
63
~FrameNode()64 FrameNode::~FrameNode()
65 {
66 for (const auto& destroyCallback : destroyCallbacks_) {
67 destroyCallback();
68 }
69 pattern_->DetachFromFrameNode(this);
70 if (IsOnMainTree()) {
71 OnDetachFromMainTree();
72 }
73 auto pipeline = PipelineContext::GetCurrentContext();
74 if (pipeline) {
75 pipeline->RemoveOnAreaChangeNode(GetId());
76 }
77 }
78
CreateFrameNodeWithTree(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern)79 RefPtr<FrameNode> FrameNode::CreateFrameNodeWithTree(
80 const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern)
81 {
82 auto newChild = CreateFrameNode(tag, nodeId, pattern, true);
83 newChild->SetDepth(1);
84 return newChild;
85 }
86
GetOrCreateFrameNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)87 RefPtr<FrameNode> FrameNode::GetOrCreateFrameNode(
88 const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
89 {
90 auto frameNode = GetFrameNode(tag, nodeId);
91 if (frameNode) {
92 return frameNode;
93 }
94 auto pattern = patternCreator ? patternCreator() : MakeRefPtr<Pattern>();
95 return CreateFrameNode(tag, nodeId, pattern);
96 }
97
GetFrameNode(const std::string & tag,int32_t nodeId)98 RefPtr<FrameNode> FrameNode::GetFrameNode(const std::string& tag, int32_t nodeId)
99 {
100 auto frameNode = ElementRegister::GetInstance()->GetSpecificItemById<FrameNode>(nodeId);
101 CHECK_NULL_RETURN_NOLOG(frameNode, nullptr);
102 if (frameNode->GetTag() != tag) {
103 LOGE("the tag is changed");
104 ElementRegister::GetInstance()->RemoveItemSilently(nodeId);
105 auto parent = frameNode->GetParent();
106 if (parent) {
107 parent->RemoveChild(frameNode);
108 }
109 return nullptr;
110 }
111 return frameNode;
112 }
113
CreateFrameNode(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern,bool isRoot)114 RefPtr<FrameNode> FrameNode::CreateFrameNode(
115 const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern, bool isRoot)
116 {
117 auto frameNode = MakeRefPtr<FrameNode>(tag, nodeId, pattern, isRoot);
118 frameNode->InitializePatternAndContext();
119 ElementRegister::GetInstance()->AddUINode(frameNode);
120 return frameNode;
121 }
122
InitializePatternAndContext()123 void FrameNode::InitializePatternAndContext()
124 {
125 eventHub_->AttachHost(WeakClaim(this));
126 pattern_->AttachToFrameNode(WeakClaim(this));
127 accessibilityProperty_->SetHost(WeakClaim(this));
128 renderContext_->SetRequestFrame([weak = WeakClaim(this)] {
129 auto frameNode = weak.Upgrade();
130 CHECK_NULL_VOID(frameNode);
131 if (frameNode->IsOnMainTree()) {
132 auto context = frameNode->GetContext();
133 CHECK_NULL_VOID(context);
134 context->RequestFrame();
135 return;
136 }
137 frameNode->hasPendingRequest_ = true;
138 });
139 renderContext_->SetHostNode(WeakClaim(this));
140 // Initialize FocusHub
141 if (pattern_->GetFocusPattern().GetFocusType() != FocusType::DISABLE) {
142 GetOrCreateFocusHub();
143 }
144 }
145
DumpInfo()146 void FrameNode::DumpInfo()
147 {
148 DumpLog::GetInstance().AddDesc(std::string("FrameRect: ").append(geometryNode_->GetFrameRect().ToString()));
149 DumpLog::GetInstance().AddDesc(
150 std::string("BackgroundColor: ").append(renderContext_->GetBackgroundColor()->ColorToString()));
151 DumpLog::GetInstance().AddDesc(std::string("ParentLayoutConstraint: ")
152 .append(geometryNode_->GetParentLayoutConstraint().has_value()
153 ? geometryNode_->GetParentLayoutConstraint().value().ToString()
154 : "NA"));
155 DumpLog::GetInstance().AddDesc(std::string("top: ")
156 .append(std::to_string(GetOffsetRelativeToWindow().GetY()))
157 .append(" left: ")
158 .append(std::to_string(GetOffsetRelativeToWindow().GetX())));
159 DumpLog::GetInstance().AddDesc(std::string("Visible: ")
160 .append(std::to_string(static_cast<int32_t>(
161 layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)))));
162 if (layoutProperty_->GetPaddingProperty()) {
163 DumpLog::GetInstance().AddDesc(
164 std::string("Padding: ").append(layoutProperty_->GetPaddingProperty()->ToString().c_str()));
165 }
166 if (layoutProperty_->GetBorderWidthProperty()) {
167 DumpLog::GetInstance().AddDesc(
168 std::string("Border: ").append(layoutProperty_->GetBorderWidthProperty()->ToString().c_str()));
169 }
170 if (layoutProperty_->GetMarginProperty()) {
171 DumpLog::GetInstance().AddDesc(
172 std::string("Margin: ").append(layoutProperty_->GetMarginProperty()->ToString().c_str()));
173 }
174 DumpLog::GetInstance().AddDesc(std::string("compid: ").append(propInspectorId_.value_or("")));
175 DumpLog::GetInstance().AddDesc(std::string("ContentConstraint: ")
176 .append(layoutProperty_->GetContentLayoutConstraint().has_value()
177 ? layoutProperty_->GetContentLayoutConstraint().value().ToString()
178 : "NA"));
179 DumpLog::GetInstance().AddDesc(
180 std::string("PaintRect: ").append(renderContext_->GetPaintRectWithTransform().ToString()));
181 if (pattern_) {
182 pattern_->DumpInfo();
183 }
184 if (renderContext_) {
185 renderContext_->DumpInfo();
186 }
187 }
188
FocusToJsonValue(std::unique_ptr<JsonValue> & json) const189 void FrameNode::FocusToJsonValue(std::unique_ptr<JsonValue>& json) const
190 {
191 bool enabled = true;
192 bool focusable = false;
193 bool focused = false;
194 bool defaultFocus = false;
195 bool groupDefaultFocus = false;
196 bool focusOnTouch = false;
197 int32_t tabIndex = 0;
198 auto focusHub = GetFocusHub();
199 if (focusHub) {
200 enabled = focusHub->IsEnabled();
201 focusable = focusHub->IsFocusable();
202 focused = focusHub->IsCurrentFocus();
203 defaultFocus = focusHub->IsDefaultFocus();
204 groupDefaultFocus = focusHub->IsDefaultGroupFocus();
205 focusOnTouch = focusHub->IsFocusOnTouch().value_or(false);
206 tabIndex = focusHub->GetTabIndex();
207 }
208 json->Put("enabled", enabled);
209 json->Put("focusable", focusable);
210 json->Put("focused", focused);
211 json->Put("defaultFocus", defaultFocus);
212 json->Put("groupDefaultFocus", groupDefaultFocus);
213 json->Put("focusOnTouch", focusOnTouch);
214 json->Put("tabIndex", tabIndex);
215 }
216
MouseToJsonValue(std::unique_ptr<JsonValue> & json) const217 void FrameNode::MouseToJsonValue(std::unique_ptr<JsonValue>& json) const
218 {
219 std::string hoverEffect = "HoverEffect.Auto";
220 auto inputEventHub = GetOrCreateInputEventHub();
221 if (inputEventHub) {
222 hoverEffect = inputEventHub->GetHoverEffectStr();
223 }
224 json->Put("hoverEffect", hoverEffect.c_str());
225 }
226
TouchToJsonValue(std::unique_ptr<JsonValue> & json) const227 void FrameNode::TouchToJsonValue(std::unique_ptr<JsonValue>& json) const
228 {
229 bool touchable = true;
230 std::string hitTestMode = "HitTestMode.Default";
231 auto gestureEventHub = GetOrCreateGestureEventHub();
232 std::vector<DimensionRect> responseRegion;
233 if (gestureEventHub) {
234 touchable = gestureEventHub->GetTouchable();
235 hitTestMode = gestureEventHub->GetHitTestModeStr();
236 responseRegion = gestureEventHub->GetResponseRegion();
237 }
238 json->Put("touchable", touchable);
239 json->Put("hitTestBehavior", hitTestMode.c_str());
240 auto jsArr = JsonUtil::CreateArray(true);
241 for (int32_t i = 0; i < static_cast<int32_t>(responseRegion.size()); ++i) {
242 auto iStr = std::to_string(i);
243 jsArr->Put(iStr.c_str(), responseRegion[i].ToJsonString().c_str());
244 }
245 json->Put("responseRegion", jsArr);
246 }
247
GeometryNodeToJsonValue(std::unique_ptr<JsonValue> & json) const248 void FrameNode::GeometryNodeToJsonValue(std::unique_ptr<JsonValue>& json) const
249 {
250 #if defined(PREVIEW)
251 bool hasIdealWidth = false;
252 bool hasIdealHeight = false;
253 if (layoutProperty_ && layoutProperty_->GetCalcLayoutConstraint()) {
254 auto selfIdealSize = layoutProperty_->GetCalcLayoutConstraint()->selfIdealSize;
255 hasIdealWidth = selfIdealSize.has_value() && selfIdealSize.value().Width().has_value();
256 hasIdealHeight = selfIdealSize.has_value() && selfIdealSize.value().Height().has_value();
257 }
258
259 auto jsonSize = json->GetValue("size");
260 if (!hasIdealWidth) {
261 auto idealWidthVpStr = std::to_string(Dimension(geometryNode_->GetFrameSize().Width()).ConvertToVp());
262 auto widthStr =
263 (idealWidthVpStr.substr(0, idealWidthVpStr.find(".") + SUBSTR_LENGTH) + DIMENSION_UNIT_VP).c_str();
264 json->Put("width", widthStr);
265 if (jsonSize) {
266 jsonSize->Put("width", widthStr);
267 }
268 }
269
270 if (!hasIdealHeight) {
271 auto idealHeightVpStr = std::to_string(Dimension(geometryNode_->GetFrameSize().Height()).ConvertToVp());
272 auto heightStr =
273 (idealHeightVpStr.substr(0, idealHeightVpStr.find(".") + SUBSTR_LENGTH) + DIMENSION_UNIT_VP).c_str();
274 json->Put("height", heightStr);
275 if (jsonSize) {
276 jsonSize->Put("height", heightStr);
277 }
278 }
279 #endif
280 }
281
ToJsonValue(std::unique_ptr<JsonValue> & json) const282 void FrameNode::ToJsonValue(std::unique_ptr<JsonValue>& json) const
283 {
284 if (renderContext_) {
285 renderContext_->ToJsonValue(json);
286 }
287 // scrollable in AccessibilityProperty
288 ACE_PROPERTY_TO_JSON_VALUE(accessibilityProperty_, AccessibilityProperty);
289 ACE_PROPERTY_TO_JSON_VALUE(layoutProperty_, LayoutProperty);
290 ACE_PROPERTY_TO_JSON_VALUE(paintProperty_, PaintProperty);
291 ACE_PROPERTY_TO_JSON_VALUE(pattern_, Pattern);
292 if (eventHub_) {
293 eventHub_->ToJsonValue(json);
294 }
295 FocusToJsonValue(json);
296 MouseToJsonValue(json);
297 TouchToJsonValue(json);
298 GeometryNodeToJsonValue(json);
299 json->Put("id", propInspectorId_.value_or("").c_str());
300 }
301
OnAttachToMainTree()302 void FrameNode::OnAttachToMainTree()
303 {
304 UINode::OnAttachToMainTree();
305 eventHub_->FireOnAppear();
306 renderContext_->OnNodeAppear();
307 if (IsResponseRegion() || HasPositionProp()) {
308 auto parent = GetParent();
309 while (parent) {
310 auto frameNode = AceType::DynamicCast<FrameNode>(parent);
311 if (frameNode) {
312 frameNode->MarkResponseRegion(true);
313 }
314 parent = parent->GetParent();
315 }
316 }
317 if (!hasPendingRequest_) {
318 return;
319 }
320 auto context = GetContext();
321 CHECK_NULL_VOID(context);
322 context->RequestFrame();
323 hasPendingRequest_ = false;
324 }
325
OnVisibleChange(bool isVisible)326 void FrameNode::OnVisibleChange(bool isVisible)
327 {
328 pattern_->OnVisibleChange(isVisible);
329 for (const auto& child : GetChildren()) {
330 child->OnVisibleChange(isVisible);
331 }
332 }
333
OnDetachFromMainTree()334 void FrameNode::OnDetachFromMainTree()
335 {
336 eventHub_->FireOnDisappear();
337 renderContext_->OnNodeDisappear();
338 }
339
SwapDirtyLayoutWrapperOnMainThread(const RefPtr<LayoutWrapper> & dirty)340 void FrameNode::SwapDirtyLayoutWrapperOnMainThread(const RefPtr<LayoutWrapper>& dirty)
341 {
342 ACE_FUNCTION_TRACE();
343 LOGD("SwapDirtyLayoutWrapperOnMainThread, %{public}s", GetTag().c_str());
344 CHECK_NULL_VOID(dirty);
345
346 // update new layout constrain.
347 layoutProperty_->UpdateLayoutConstraint(dirty->GetLayoutProperty());
348
349 // active change flag judge.
350 SetActive(dirty->IsActive());
351 if (!isActive_) {
352 LOGD("current node is inactive, don't need to render");
353 return;
354 }
355
356 // update layout size.
357 bool frameSizeChange = geometryNode_->GetFrameSize() != dirty->GetGeometryNode()->GetFrameSize();
358 bool frameOffsetChange = geometryNode_->GetFrameOffset() != dirty->GetGeometryNode()->GetFrameOffset();
359 bool contentSizeChange = geometryNode_->GetContentSize() != dirty->GetGeometryNode()->GetContentSize();
360 bool contentOffsetChange = geometryNode_->GetContentOffset() != dirty->GetGeometryNode()->GetContentOffset();
361
362 SetGeometryNode(dirty->GetGeometryNode());
363 if (frameSizeChange || frameOffsetChange || HasPositionProp() ||
364 (pattern_->GetSurfaceNodeName().has_value() && contentSizeChange)) {
365 if (pattern_->NeedOverridePaintRect()) {
366 renderContext_->SyncGeometryProperties(pattern_->GetOverridePaintRect().value_or(RectF()));
367 } else {
368 renderContext_->SyncGeometryProperties(RawPtr(dirty->GetGeometryNode()));
369 }
370 }
371
372 // clean layout flag.
373 layoutProperty_->CleanDirty();
374 DirtySwapConfig config { frameSizeChange, frameOffsetChange, contentSizeChange, contentOffsetChange };
375 // check if need to paint content.
376 auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
377 CHECK_NULL_VOID(layoutAlgorithmWrapper);
378 config.skipMeasure = layoutAlgorithmWrapper->SkipMeasure() || dirty->SkipMeasureContent();
379 config.skipLayout = layoutAlgorithmWrapper->SkipLayout();
380 auto needRerender = pattern_->OnDirtyLayoutWrapperSwap(dirty, config);
381 // TODO: temp use and need to delete.
382 needRerender = needRerender || pattern_->OnDirtyLayoutWrapperSwap(dirty, config.skipMeasure, config.skipLayout);
383 if (needRerender || CheckNeedRender(paintProperty_->GetPropertyChangeFlag())) {
384 MarkDirtyNode(true, true, PROPERTY_UPDATE_RENDER);
385 }
386
387 // update border.
388 if (layoutProperty_->GetBorderWidthProperty()) {
389 if (!renderContext_->HasBorderColor()) {
390 BorderColorProperty borderColorProperty;
391 borderColorProperty.SetColor(Color::BLACK);
392 renderContext_->UpdateBorderColor(borderColorProperty);
393 }
394 if (!renderContext_->HasBorderStyle()) {
395 BorderStyleProperty borderStyleProperty;
396 borderStyleProperty.SetBorderStyle(BorderStyle::SOLID);
397 renderContext_->UpdateBorderStyle(borderStyleProperty);
398 }
399 if (layoutProperty_->GetLayoutConstraint().has_value()) {
400 renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
401 ScaleProperty::CreateScaleProperty(),
402 layoutProperty_->GetLayoutConstraint()->percentReference.Width()));
403 } else {
404 renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
405 ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth()));
406 }
407 }
408
409 // update focus state
410 auto focusHub = GetFocusHub();
411 if (focusHub && focusHub->IsCurrentFocus()) {
412 focusHub->ClearFocusState();
413 focusHub->PaintFocusState();
414 }
415
416 // rebuild child render node.
417 RebuildRenderContextTree();
418 }
419
AdjustGridOffset()420 void FrameNode::AdjustGridOffset()
421 {
422 if (!isActive_) {
423 return;
424 }
425 if (layoutProperty_->UpdateGridOffset(Claim(this))) {
426 renderContext_->UpdateOffset(OffsetT<Dimension>());
427 renderContext_->UpdateAnchor(OffsetT<Dimension>());
428 renderContext_->SyncGeometryProperties(RawPtr(GetGeometryNode()));
429 }
430 }
431
SetOnAreaChangeCallback(OnAreaChangedFunc && callback)432 void FrameNode::SetOnAreaChangeCallback(OnAreaChangedFunc&& callback)
433 {
434 if (!lastFrameRect_) {
435 lastFrameRect_ = std::make_unique<RectF>();
436 }
437 if (!lastParentOffsetToWindow_) {
438 lastParentOffsetToWindow_ = std::make_unique<OffsetF>();
439 }
440 eventHub_->SetOnAreaChanged(std::move(callback));
441 }
442
TriggerOnAreaChangeCallback()443 void FrameNode::TriggerOnAreaChangeCallback()
444 {
445 if (eventHub_->HasOnAreaChanged() && lastFrameRect_ && lastParentOffsetToWindow_) {
446 auto currFrameRect = geometryNode_->GetFrameRect();
447 auto currParentOffsetToWindow = GetOffsetRelativeToWindow() - currFrameRect.GetOffset();
448 if (currFrameRect != *lastFrameRect_ || currParentOffsetToWindow != *lastParentOffsetToWindow_) {
449 eventHub_->FireOnAreaChanged(
450 *lastFrameRect_, *lastParentOffsetToWindow_, currFrameRect, currParentOffsetToWindow);
451 *lastFrameRect_ = currFrameRect;
452 *lastParentOffsetToWindow_ = currParentOffsetToWindow;
453 }
454 }
455 pattern_->OnAreaChangedInner();
456 }
457
TriggerVisibleAreaChangeCallback(std::list<VisibleCallbackInfo> & callbackInfoList)458 void FrameNode::TriggerVisibleAreaChangeCallback(std::list<VisibleCallbackInfo>& callbackInfoList)
459 {
460 auto context = PipelineContext::GetCurrentContext();
461 CHECK_NULL_VOID(context);
462
463 bool curFrameIsActive = true;
464 auto parent = GetParent();
465 while (parent) {
466 auto parentFrame = AceType::DynamicCast<FrameNode>(parent);
467 if (!parentFrame) {
468 parent = parent->GetParent();
469 continue;
470 }
471 if (!parentFrame->isActive_) {
472 curFrameIsActive = false;
473 break;
474 }
475 parent = parent->GetParent();
476 }
477
478 if (!context->GetOnShow() || !IsVisible() || !curFrameIsActive) {
479 if (!NearEqual(lastVisibleRatio_, VISIBLE_RATIO_MIN)) {
480 ProcessAllVisibleCallback(callbackInfoList, VISIBLE_RATIO_MIN);
481 lastVisibleRatio_ = VISIBLE_RATIO_MIN;
482 }
483 return;
484 }
485
486 auto frameRect = renderContext_->GetPaintRectWithTransform();
487 frameRect.SetOffset(GetOffsetRelativeToWindow());
488 auto visibleRect = frameRect;
489 RectF parentRect;
490 auto parentUi = GetParent();
491 while (parentUi) {
492 auto parentFrame = AceType::DynamicCast<FrameNode>(parentUi);
493 if (!parentFrame) {
494 parentUi = parentUi->GetParent();
495 continue;
496 }
497 parentRect = parentFrame->GetRenderContext()->GetPaintRectWithTransform();
498 parentRect.SetOffset(parentFrame->GetOffsetRelativeToWindow());
499 visibleRect = visibleRect.Constrain(parentRect);
500 parentUi = parentUi->GetParent();
501 }
502
503 double currentVisibleRatio =
504 std::clamp(CalculateCurrentVisibleRatio(visibleRect, frameRect), VISIBLE_RATIO_MIN, VISIBLE_RATIO_MAX);
505 if (!NearEqual(currentVisibleRatio, lastVisibleRatio_)) {
506 ProcessAllVisibleCallback(callbackInfoList, currentVisibleRatio);
507 lastVisibleRatio_ = currentVisibleRatio;
508 }
509 }
510
CalculateCurrentVisibleRatio(const RectF & visibleRect,const RectF & renderRect)511 double FrameNode::CalculateCurrentVisibleRatio(const RectF& visibleRect, const RectF& renderRect)
512 {
513 if (!visibleRect.IsValid() || !renderRect.IsValid()) {
514 return 0.0;
515 }
516 return visibleRect.Width() * visibleRect.Height() / (renderRect.Width() * renderRect.Height());
517 }
518
ProcessAllVisibleCallback(std::list<VisibleCallbackInfo> & callbackInfoList,double currentVisibleRatio)519 void FrameNode::ProcessAllVisibleCallback(std::list<VisibleCallbackInfo>& callbackInfoList, double currentVisibleRatio)
520 {
521 for (auto& nodeCallbackInfo : callbackInfoList) {
522 if (GreatNotEqual(currentVisibleRatio, nodeCallbackInfo.visibleRatio) && !nodeCallbackInfo.isCurrentVisible) {
523 OnVisibleAreaChangeCallback(nodeCallbackInfo, true, currentVisibleRatio);
524 continue;
525 }
526
527 if (LessNotEqual(currentVisibleRatio, nodeCallbackInfo.visibleRatio) && nodeCallbackInfo.isCurrentVisible) {
528 OnVisibleAreaChangeCallback(nodeCallbackInfo, false, currentVisibleRatio);
529 continue;
530 }
531
532 if (NearEqual(currentVisibleRatio, nodeCallbackInfo.visibleRatio) &&
533 NearEqual(nodeCallbackInfo.visibleRatio, VISIBLE_RATIO_MIN)) {
534 if (nodeCallbackInfo.isCurrentVisible) {
535 OnVisibleAreaChangeCallback(nodeCallbackInfo, false, VISIBLE_RATIO_MIN);
536 } else {
537 OnVisibleAreaChangeCallback(nodeCallbackInfo, true, VISIBLE_RATIO_MIN);
538 }
539 } else if (NearEqual(currentVisibleRatio, nodeCallbackInfo.visibleRatio) &&
540 NearEqual(nodeCallbackInfo.visibleRatio, VISIBLE_RATIO_MAX)) {
541 if (!nodeCallbackInfo.isCurrentVisible) {
542 OnVisibleAreaChangeCallback(nodeCallbackInfo, true, VISIBLE_RATIO_MAX);
543 } else {
544 OnVisibleAreaChangeCallback(nodeCallbackInfo, false, VISIBLE_RATIO_MAX);
545 }
546 }
547 }
548 }
549
OnVisibleAreaChangeCallback(VisibleCallbackInfo & callbackInfo,bool visibleType,double currentVisibleRatio)550 void FrameNode::OnVisibleAreaChangeCallback(
551 VisibleCallbackInfo& callbackInfo, bool visibleType, double currentVisibleRatio)
552 {
553 callbackInfo.isCurrentVisible = visibleType;
554 if (callbackInfo.callback) {
555 callbackInfo.callback(visibleType, currentVisibleRatio);
556 }
557 }
558
SetActive(bool active)559 void FrameNode::SetActive(bool active)
560 {
561 bool activeChanged = false;
562 if (active && !isActive_) {
563 pattern_->OnActive();
564 isActive_ = true;
565 activeChanged = true;
566 }
567 if (!active && isActive_) {
568 pattern_->OnInActive();
569 isActive_ = false;
570 activeChanged = true;
571 }
572 if (activeChanged) {
573 auto parent = GetAncestorNodeOfFrame();
574 if (parent) {
575 parent->MarkNeedSyncRenderTree();
576 }
577 }
578 }
579
SetGeometryNode(const RefPtr<GeometryNode> & node)580 void FrameNode::SetGeometryNode(const RefPtr<GeometryNode>& node)
581 {
582 geometryNode_ = node;
583 }
584
CreateLayoutTask(bool forceUseMainThread)585 std::optional<UITask> FrameNode::CreateLayoutTask(bool forceUseMainThread)
586 {
587 if (!isLayoutDirtyMarked_) {
588 return std::nullopt;
589 }
590 ACE_SCOPED_TRACE("CreateLayoutTask:PrepareTask");
591 RefPtr<LayoutWrapper> layoutWrapper;
592 UpdateLayoutPropertyFlag();
593 layoutWrapper = CreateLayoutWrapper();
594 CHECK_NULL_RETURN_NOLOG(layoutWrapper, std::nullopt);
595 auto task = [layoutWrapper, layoutConstraint = GetLayoutConstraint(), forceUseMainThread]() {
596 layoutWrapper->SetActive();
597 layoutWrapper->SetRootMeasureNode();
598 {
599 ACE_SCOPED_TRACE("LayoutWrapper::Measure");
600 layoutWrapper->Measure(layoutConstraint);
601 }
602 {
603 ACE_SCOPED_TRACE("LayoutWrapper::Layout");
604 layoutWrapper->Layout();
605 }
606 {
607 ACE_SCOPED_TRACE("LayoutWrapper::MountToHostOnMainThread");
608 if (forceUseMainThread || layoutWrapper->CheckShouldRunOnMain()) {
609 layoutWrapper->MountToHostOnMainThread();
610 return;
611 }
612 auto host = layoutWrapper->GetHostNode();
613 CHECK_NULL_VOID(host);
614 host->PostTask([layoutWrapper]() { layoutWrapper->MountToHostOnMainThread(); });
615 }
616 };
617 if (forceUseMainThread || layoutWrapper->CheckShouldRunOnMain()) {
618 return UITask(std::move(task), MAIN_TASK);
619 }
620 return UITask(std::move(task), layoutWrapper->CanRunOnWhichThread());
621 }
622
CreateRenderTask(bool forceUseMainThread)623 std::optional<UITask> FrameNode::CreateRenderTask(bool forceUseMainThread)
624 {
625 if (!isRenderDirtyMarked_) {
626 return std::nullopt;
627 }
628 ACE_SCOPED_TRACE("CreateRenderTask:PrepareTask");
629 auto wrapper = CreatePaintWrapper();
630 CHECK_NULL_RETURN_NOLOG(wrapper, std::nullopt);
631 auto task = [wrapper, paintProperty = paintProperty_]() {
632 ACE_SCOPED_TRACE("FrameNode::RenderTask");
633 wrapper->FlushRender();
634 paintProperty->CleanDirty();
635 };
636 if (forceUseMainThread || wrapper->CheckShouldRunOnMain()) {
637 return UITask(std::move(task), MAIN_TASK);
638 }
639 return UITask(std::move(task), wrapper->CanRunOnWhichThread());
640 }
641
GetLayoutConstraint() const642 LayoutConstraintF FrameNode::GetLayoutConstraint() const
643 {
644 if (geometryNode_->GetParentLayoutConstraint().has_value()) {
645 return geometryNode_->GetParentLayoutConstraint().value();
646 }
647 LayoutConstraintF layoutConstraint;
648 layoutConstraint.scaleProperty = ScaleProperty::CreateScaleProperty();
649 auto rootWidth = PipelineContext::GetCurrentRootWidth();
650 auto rootHeight = PipelineContext::GetCurrentRootHeight();
651 layoutConstraint.percentReference.SetWidth(rootWidth);
652 layoutConstraint.percentReference.SetHeight(rootHeight);
653 layoutConstraint.maxSize.SetWidth(rootWidth);
654 layoutConstraint.maxSize.SetHeight(rootHeight);
655 return layoutConstraint;
656 }
657
GetParentGlobalOffset() const658 OffsetF FrameNode::GetParentGlobalOffset() const
659 {
660 auto parent = GetAncestorNodeOfFrame();
661 if (!parent) {
662 return { 0.0f, 0.0f };
663 }
664 return parent->geometryNode_->GetParentGlobalOffset();
665 }
666
UpdateLayoutPropertyFlag()667 void FrameNode::UpdateLayoutPropertyFlag()
668 {
669 auto selfFlag = layoutProperty_->GetPropertyChangeFlag();
670 if (!CheckUpdateByChildRequest(selfFlag)) {
671 return;
672 }
673 if (CheckForceParentMeasureFlag(selfFlag)) {
674 return;
675 }
676 auto flag = PROPERTY_UPDATE_NORMAL;
677 const auto& children = GetChildren();
678 for (const auto& child : children) {
679 child->UpdateLayoutPropertyFlag();
680 child->AdjustParentLayoutFlag(flag);
681 if (CheckForceParentMeasureFlag(selfFlag)) {
682 break;
683 }
684 }
685 if (CheckForceParentMeasureFlag(flag)) {
686 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
687 }
688 }
689
AdjustParentLayoutFlag(PropertyChangeFlag & flag)690 void FrameNode::AdjustParentLayoutFlag(PropertyChangeFlag& flag)
691 {
692 flag = flag | layoutProperty_->GetPropertyChangeFlag();
693 }
694
CreateLayoutWrapper(bool forceMeasure,bool forceLayout)695 RefPtr<LayoutWrapper> FrameNode::CreateLayoutWrapper(bool forceMeasure, bool forceLayout)
696 {
697 CHECK_NULL_RETURN_NOLOG(layoutProperty_, nullptr);
698 CHECK_NULL_RETURN_NOLOG(pattern_, nullptr);
699 if (layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE) == VisibleType::GONE) {
700 auto layoutWrapper =
701 MakeRefPtr<LayoutWrapper>(WeakClaim(this), MakeRefPtr<GeometryNode>(), layoutProperty_->Clone());
702 layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(nullptr, true, true));
703 isLayoutDirtyMarked_ = false;
704 return layoutWrapper;
705 }
706
707 pattern_->BeforeCreateLayoutWrapper();
708 if (!isActive_ || forceMeasure) {
709 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
710 }
711 if (forceLayout) {
712 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_LAYOUT);
713 }
714 auto flag = layoutProperty_->GetPropertyChangeFlag();
715 // It is necessary to copy the layoutProperty property to prevent the layoutProperty property from being modified
716 // during the layout process, resulting in the problem of judging whether the front-end setting value changes the
717 // next time js is executed.
718 auto layoutWrapper = MakeRefPtr<LayoutWrapper>(WeakClaim(this), geometryNode_->Clone(), layoutProperty_->Clone());
719 LOGD("%{public}s create layout wrapper: %{public}x, %{public}d, %{public}d", GetTag().c_str(), flag, forceMeasure,
720 forceLayout);
721 do {
722 if (CheckNeedMeasure(flag) || forceMeasure) {
723 layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm()));
724 bool forceChildMeasure = CheckMeasureFlag(flag) || CheckMeasureSelfAndChildFlag(flag) || forceMeasure;
725 UpdateChildrenLayoutWrapper(layoutWrapper, forceChildMeasure, false);
726 break;
727 }
728 if (CheckNeedLayout(flag) || forceLayout) {
729 layoutWrapper->SetLayoutAlgorithm(
730 MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm(), true, false));
731 UpdateChildrenLayoutWrapper(layoutWrapper, false, false);
732 break;
733 }
734 layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(nullptr, true, true));
735 } while (false);
736 // check position flag.
737 layoutWrapper->SetOutOfLayout(renderContext_->HasPosition());
738 layoutWrapper->SetActive(isActive_);
739 isLayoutDirtyMarked_ = false;
740 return layoutWrapper;
741 }
742
UpdateChildrenLayoutWrapper(const RefPtr<LayoutWrapper> & self,bool forceMeasure,bool forceLayout)743 void FrameNode::UpdateChildrenLayoutWrapper(const RefPtr<LayoutWrapper>& self, bool forceMeasure, bool forceLayout)
744 {
745 const auto& children = GetChildren();
746 for (const auto& child : children) {
747 child->AdjustLayoutWrapperTree(self, forceMeasure, forceLayout);
748 }
749 }
750
AdjustLayoutWrapperTree(const RefPtr<LayoutWrapper> & parent,bool forceMeasure,bool forceLayout)751 void FrameNode::AdjustLayoutWrapperTree(const RefPtr<LayoutWrapper>& parent, bool forceMeasure, bool forceLayout)
752 {
753 ACE_DCHECK(parent);
754 auto layoutWrapper = CreateLayoutWrapper(forceMeasure, forceLayout);
755 parent->AppendChild(layoutWrapper);
756 }
757
CreatePaintWrapper()758 RefPtr<PaintWrapper> FrameNode::CreatePaintWrapper()
759 {
760 pattern_->BeforeCreatePaintWrapper();
761 isRenderDirtyMarked_ = false;
762 auto paintMethod = pattern_->CreateNodePaintMethod();
763 // It is necessary to copy the layoutProperty property to prevent the paintProperty_ property from being modified
764 // during the paint process, resulting in the problem of judging whether the front-end setting value changes the
765 // next time js is executed.
766 if (paintMethod) {
767 auto paintWrapper = MakeRefPtr<PaintWrapper>(renderContext_, geometryNode_->Clone(), paintProperty_->Clone());
768 paintWrapper->SetNodePaintMethod(paintMethod);
769 return paintWrapper;
770 }
771 if (renderContext_->GetAccessibilityFocus().value_or(false)) {
772 auto paintWrapper = MakeRefPtr<PaintWrapper>(renderContext_, geometryNode_->Clone(), paintProperty_->Clone());
773 paintWrapper->SetNodePaintMethod(MakeRefPtr<NodePaintMethod>());
774 return paintWrapper;
775 }
776 return nullptr;
777 }
778
PostTask(std::function<void ()> && task,TaskExecutor::TaskType taskType)779 void FrameNode::PostTask(std::function<void()>&& task, TaskExecutor::TaskType taskType)
780 {
781 auto context = GetContext();
782 CHECK_NULL_VOID(context);
783 context->PostAsyncEvent(std::move(task), taskType);
784 }
785
UpdateLayoutConstraint(const MeasureProperty & calcLayoutConstraint)786 void FrameNode::UpdateLayoutConstraint(const MeasureProperty& calcLayoutConstraint)
787 {
788 layoutProperty_->UpdateCalcLayoutProperty(calcLayoutConstraint);
789 }
790
RebuildRenderContextTree()791 void FrameNode::RebuildRenderContextTree()
792 {
793 if (!needSyncRenderTree_) {
794 return;
795 }
796 frameChildren_.clear();
797 std::list<RefPtr<FrameNode>> children;
798 GenerateOneDepthVisibleFrame(children);
799 frameChildren_ = { children.begin(), children.end() };
800 renderContext_->RebuildFrame(this, children);
801 pattern_->OnRebuildFrame();
802 needSyncRenderTree_ = false;
803 }
804
MarkModifyDone()805 void FrameNode::MarkModifyDone()
806 {
807 pattern_->OnModifyDone();
808 eventHub_->MarkModifyDone();
809 if (IsResponseRegion() || HasPositionProp()) {
810 auto parent = GetParent();
811 while (parent) {
812 auto frameNode = AceType::DynamicCast<FrameNode>(parent);
813 if (frameNode) {
814 frameNode->MarkResponseRegion(true);
815 }
816 parent = parent->GetParent();
817 }
818 }
819 renderContext_->OnModifyDone();
820 }
821
OnMountToParentDone()822 void FrameNode::OnMountToParentDone()
823 {
824 pattern_->OnMountToParentDone();
825 }
826
FlushUpdateAndMarkDirty()827 void FrameNode::FlushUpdateAndMarkDirty()
828 {
829 MarkDirtyNode();
830 }
831
MarkDirtyNode(PropertyChangeFlag extraFlag)832 void FrameNode::MarkDirtyNode(PropertyChangeFlag extraFlag)
833 {
834 MarkDirtyNode(IsMeasureBoundary(), IsRenderBoundary(), extraFlag);
835 }
836
GetAncestorNodeOfFrame() const837 RefPtr<FrameNode> FrameNode::GetAncestorNodeOfFrame() const
838 {
839 auto parent = GetParent();
840 while (parent) {
841 if (InstanceOf<FrameNode>(parent)) {
842 return DynamicCast<FrameNode>(parent);
843 }
844 parent = parent->GetParent();
845 }
846 return nullptr;
847 }
848
MarkNeedRenderOnly()849 void FrameNode::MarkNeedRenderOnly()
850 {
851 MarkNeedRender(IsRenderBoundary());
852 }
853
MarkNeedRender(bool isRenderBoundary)854 void FrameNode::MarkNeedRender(bool isRenderBoundary)
855 {
856 auto context = GetContext();
857 CHECK_NULL_VOID(context);
858 // If it has dirtyLayoutBox, need to mark dirty after layout done.
859 paintProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_RENDER);
860 if (isRenderDirtyMarked_ || isLayoutDirtyMarked_) {
861 LOGD("this node has already mark dirty, %{public}s, %{public}d, %{public}d", GetTag().c_str(),
862 isRenderDirtyMarked_, isLayoutDirtyMarked_);
863 return;
864 }
865 isRenderDirtyMarked_ = true;
866 if (isRenderBoundary) {
867 context->AddDirtyRenderNode(Claim(this));
868 return;
869 }
870 auto parent = GetAncestorNodeOfFrame();
871 if (parent) {
872 parent->MarkDirtyNode(PROPERTY_UPDATE_RENDER_BY_CHILD_REQUEST);
873 }
874 }
875
MarkDirtyNode(bool isMeasureBoundary,bool isRenderBoundary,PropertyChangeFlag extraFlag)876 void FrameNode::MarkDirtyNode(bool isMeasureBoundary, bool isRenderBoundary, PropertyChangeFlag extraFlag)
877 {
878 if (CheckNeedRender(extraFlag)) {
879 paintProperty_->UpdatePropertyChangeFlag(extraFlag);
880 }
881 layoutProperty_->UpdatePropertyChangeFlag(extraFlag);
882 paintProperty_->UpdatePropertyChangeFlag(extraFlag);
883 auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
884 auto paintFlag = paintProperty_->GetPropertyChangeFlag();
885 if (CheckNoChanged(layoutFlag | paintFlag)) {
886 LOGD("MarkDirtyNode: flag not changed, node tag: %{public}s", GetTag().c_str());
887 return;
888 }
889 auto context = GetContext();
890 CHECK_NULL_VOID(context);
891
892 if (CheckNeedRequestMeasureAndLayout(layoutFlag)) {
893 if (!isMeasureBoundary && IsNeedRequestParentMeasure()) {
894 auto parent = GetAncestorNodeOfFrame();
895 if (parent) {
896 parent->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
897 return;
898 }
899 }
900 if (isLayoutDirtyMarked_) {
901 LOGD("MarkDirtyNode: isLayoutDirtyMarked is true");
902 return;
903 }
904 isLayoutDirtyMarked_ = true;
905 context->AddDirtyLayoutNode(Claim(this));
906 return;
907 }
908 layoutProperty_->CleanDirty();
909 MarkNeedRender(isRenderBoundary);
910 }
911
IsNeedRequestParentMeasure() const912 bool FrameNode::IsNeedRequestParentMeasure() const
913 {
914 auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
915 if (layoutFlag == PROPERTY_UPDATE_BY_CHILD_REQUEST) {
916 const auto& calcLayoutConstraint = layoutProperty_->GetCalcLayoutConstraint();
917 if (calcLayoutConstraint && calcLayoutConstraint->selfIdealSize &&
918 calcLayoutConstraint->selfIdealSize->IsValid()) {
919 LOGD("make self measure boundary");
920 return false;
921 }
922 }
923 return CheckNeedRequestParentMeasure(layoutFlag);
924 }
925
OnGenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>> & visibleList)926 void FrameNode::OnGenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>>& visibleList)
927 {
928 if (isActive_ && IsVisible()) {
929 visibleList.emplace_back(Claim(this));
930 }
931 }
932
OnGenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>> & allList)933 void FrameNode::OnGenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>>& allList)
934 {
935 allList.emplace_back(Claim(this));
936 }
937
IsMeasureBoundary()938 bool FrameNode::IsMeasureBoundary()
939 {
940 return isMeasureBoundary_ || pattern_->IsMeasureBoundary();
941 }
942
IsRenderBoundary()943 bool FrameNode::IsRenderBoundary()
944 {
945 return pattern_->IsRenderBoundary();
946 }
947
GetPattern() const948 const RefPtr<Pattern>& FrameNode::GetPattern() const
949 {
950 return pattern_;
951 }
952
IsAtomicNode() const953 bool FrameNode::IsAtomicNode() const
954 {
955 return pattern_->IsAtomicNode();
956 }
957
GetHitTestMode() const958 HitTestMode FrameNode::GetHitTestMode() const
959 {
960 auto gestureHub = eventHub_->GetGestureEventHub();
961 return gestureHub ? gestureHub->GetHitTestMode() : HitTestMode::HTMDEFAULT;
962 }
963
GetTouchable() const964 bool FrameNode::GetTouchable() const
965 {
966 auto gestureHub = eventHub_->GetGestureEventHub();
967 return gestureHub ? gestureHub->GetTouchable() : true;
968 }
969
IsResponseRegion() const970 bool FrameNode::IsResponseRegion() const
971 {
972 if (!pattern_->UsResRegion()) {
973 return false;
974 }
975 auto gestureHub = eventHub_->GetGestureEventHub();
976 return gestureHub ? gestureHub->IsResponseRegion() : false;
977 }
978
MarkResponseRegion(bool isResponseRegion)979 void FrameNode::MarkResponseRegion(bool isResponseRegion)
980 {
981 auto gestureHub = eventHub_->GetOrCreateGestureEventHub();
982 if (gestureHub) {
983 gestureHub->MarkResponseRegion(isResponseRegion);
984 }
985 }
986
IsOutOfTouchTestRegion(const PointF & parentLocalPoint)987 bool FrameNode::IsOutOfTouchTestRegion(const PointF& parentLocalPoint)
988 {
989 bool isInChildRegion = false;
990 auto paintRect = renderContext_->GetPaintRectWithTransform();
991 auto responseRegionList = GetResponseRegionList(paintRect);
992 auto localPoint = parentLocalPoint - paintRect.GetOffset();
993 if (!InResponseRegionList(parentLocalPoint, responseRegionList) || !GetTouchable()) {
994 if (!pattern_->UsResRegion()) {
995 LOGD("TouchTest: not use resRegion, point is out of region in %{public}s", GetTag().c_str());
996 return true;
997 }
998 for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
999 const auto& child = *iter;
1000 if (!child->IsOutOfTouchTestRegion(localPoint)) {
1001 LOGD("TouchTest: point is out of region in %{public}s, but is in child region", GetTag().c_str());
1002 isInChildRegion = true;
1003 break;
1004 }
1005 }
1006 if (!isInChildRegion) {
1007 LOGD("TouchTest: point is out of region in %{public}s", GetTag().c_str());
1008 return true;
1009 }
1010 }
1011 return false;
1012 }
1013
TouchTest(const PointF & globalPoint,const PointF & parentLocalPoint,const TouchRestrict & touchRestrict,TouchTestResult & result,int32_t touchId)1014 HitTestResult FrameNode::TouchTest(const PointF& globalPoint, const PointF& parentLocalPoint,
1015 const TouchRestrict& touchRestrict, TouchTestResult& result, int32_t touchId)
1016 {
1017 if (!isActive_ || !eventHub_->IsEnabled()) {
1018 LOGE("%{public}s is inActive, need't do touch test", GetTag().c_str());
1019 return HitTestResult::OUT_OF_REGION;
1020 }
1021 auto paintRect = renderContext_->GetPaintRectWithTransform();
1022 auto responseRegionList = GetResponseRegionList(paintRect);
1023 if (SystemProperties::GetDebugEnabled()) {
1024 LOGD("TouchTest: point is %{public}s in %{public}s, depth: %{public}d", parentLocalPoint.ToString().c_str(),
1025 GetTag().c_str(), GetDepth());
1026 for (const auto& rect : responseRegionList) {
1027 LOGD("TouchTest: responseRegionList is %{public}s, point is %{public}s", rect.ToString().c_str(),
1028 parentLocalPoint.ToString().c_str());
1029 }
1030 }
1031
1032 if (IsOutOfTouchTestRegion(parentLocalPoint)) {
1033 return HitTestResult::OUT_OF_REGION;
1034 }
1035
1036 HitTestResult testResult = HitTestResult::OUT_OF_REGION;
1037 bool preventBubbling = false;
1038 // Child nodes are repackaged into gesture groups (parallel gesture groups, exclusive gesture groups, etc.) based on
1039 // the gesture attributes set by the current parent node (high and low priority, parallel gestures, etc.), the
1040 // newComingTargets is the template object to collect child nodes gesture and used by gestureHub to pack gesture
1041 // group.
1042 TouchTestResult newComingTargets;
1043 auto tmp = parentLocalPoint - paintRect.GetOffset();
1044 renderContext_->GetPointWithTransform(tmp);
1045 const auto localPoint = tmp;
1046 bool consumed = false;
1047 for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
1048 if (GetHitTestMode() == HitTestMode::HTMBLOCK) {
1049 break;
1050 }
1051
1052 const auto& child = *iter;
1053 auto childHitResult = child->TouchTest(globalPoint, localPoint, touchRestrict, newComingTargets, touchId);
1054 if (childHitResult == HitTestResult::STOP_BUBBLING) {
1055 preventBubbling = true;
1056 consumed = true;
1057 if ((child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
1058 (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF)) {
1059 break;
1060 }
1061 }
1062
1063 // In normal process, the node block the brother node.
1064 if (childHitResult == HitTestResult::BUBBLING &&
1065 ((child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
1066 (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF))) {
1067 consumed = true;
1068 break;
1069 }
1070 }
1071
1072 // first update HitTestResult by children status.
1073 if (consumed) {
1074 testResult = preventBubbling ? HitTestResult::STOP_BUBBLING : HitTestResult::BUBBLING;
1075 consumed = false;
1076 }
1077
1078 if (!preventBubbling && (GetHitTestMode() != HitTestMode::HTMNONE) &&
1079 InResponseRegionList(parentLocalPoint, responseRegionList)) {
1080 consumed = true;
1081 if (touchRestrict.hitTestType == SourceType::TOUCH) {
1082 auto gestureHub = eventHub_->GetGestureEventHub();
1083 if (gestureHub) {
1084 TouchTestResult finalResult;
1085 const auto coordinateOffset = globalPoint - localPoint;
1086 preventBubbling = gestureHub->ProcessTouchTestHit(
1087 coordinateOffset, touchRestrict, newComingTargets, finalResult, touchId);
1088 newComingTargets.swap(finalResult);
1089 }
1090 } else if (touchRestrict.hitTestType == SourceType::MOUSE) {
1091 auto mouseHub = eventHub_->GetInputEventHub();
1092 if (mouseHub) {
1093 const auto coordinateOffset = globalPoint - localPoint;
1094 preventBubbling = mouseHub->ProcessMouseTestHit(coordinateOffset, newComingTargets);
1095 }
1096 }
1097 }
1098
1099 result.splice(result.end(), std::move(newComingTargets));
1100 if (touchRestrict.hitTestType == SourceType::TOUCH) {
1101 // combine into exclusive recognizer group.
1102 auto gestureHub = eventHub_->GetGestureEventHub();
1103 if (gestureHub) {
1104 gestureHub->CombineIntoExclusiveRecognizer(globalPoint, localPoint, result, touchId);
1105 }
1106 }
1107
1108 // consumed by children and return result.
1109 if (!consumed) {
1110 return testResult;
1111 }
1112
1113 if (testResult == HitTestResult::OUT_OF_REGION) {
1114 // consume only by self.
1115 if (preventBubbling) {
1116 return HitTestResult::STOP_BUBBLING;
1117 }
1118 return (GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ? HitTestResult::SELF_TRANSPARENT
1119 : HitTestResult::BUBBLING;
1120 }
1121 // consume by self and children.
1122 return testResult;
1123 }
1124
GetResponseRegionList(const RectF & rect)1125 std::vector<RectF> FrameNode::GetResponseRegionList(const RectF& rect)
1126 {
1127 std::vector<RectF> responseRegionList;
1128 auto gestureHub = eventHub_->GetGestureEventHub();
1129 if (!gestureHub) {
1130 responseRegionList.emplace_back(rect);
1131 return responseRegionList;
1132 }
1133
1134 if (gestureHub->GetResponseRegion().empty()) {
1135 responseRegionList.emplace_back(rect);
1136 return responseRegionList;
1137 }
1138
1139 auto scaleProperty = ScaleProperty::CreateScaleProperty();
1140 for (const auto& region : gestureHub->GetResponseRegion()) {
1141 auto x = ConvertToPx(region.GetOffset().GetX(), scaleProperty, rect.Width());
1142 auto y = ConvertToPx(region.GetOffset().GetY(), scaleProperty, rect.Height());
1143 auto width = ConvertToPx(region.GetWidth(), scaleProperty, rect.Width());
1144 auto height = ConvertToPx(region.GetHeight(), scaleProperty, rect.Height());
1145 RectF responseRegion(
1146 rect.GetOffset().GetX() + x.value(), rect.GetOffset().GetY() + y.value(), width.value(), height.value());
1147 responseRegionList.emplace_back(responseRegion);
1148 }
1149 return responseRegionList;
1150 }
1151
InResponseRegionList(const PointF & parentLocalPoint,const std::vector<RectF> & responseRegionList) const1152 bool FrameNode::InResponseRegionList(const PointF& parentLocalPoint, const std::vector<RectF>& responseRegionList) const
1153 {
1154 for (const auto& rect : responseRegionList) {
1155 if (rect.IsInRegion(parentLocalPoint)) {
1156 return true;
1157 }
1158 }
1159 return false;
1160 }
1161
MouseTest(const PointF & globalPoint,const PointF & parentLocalPoint,MouseTestResult & onMouseResult,MouseTestResult & onHoverResult,RefPtr<FrameNode> & hoverNode)1162 HitTestResult FrameNode::MouseTest(const PointF& globalPoint, const PointF& parentLocalPoint,
1163 MouseTestResult& onMouseResult, MouseTestResult& onHoverResult, RefPtr<FrameNode>& hoverNode)
1164 {
1165 // unuseable function. do nothing.
1166 return HitTestResult::BUBBLING;
1167 }
1168
AxisTest(const PointF & globalPoint,const PointF & parentLocalPoint,AxisTestResult & onAxisResult)1169 HitTestResult FrameNode::AxisTest(
1170 const PointF& globalPoint, const PointF& parentLocalPoint, AxisTestResult& onAxisResult)
1171 {
1172 const auto& rect = renderContext_->GetPaintRectWithTransform();
1173 LOGD("AxisTest: type is %{public}s, the region is %{public}lf, %{public}lf, %{public}lf, %{public}lf",
1174 GetTag().c_str(), rect.Left(), rect.Top(), rect.Width(), rect.Height());
1175 // TODO: disableTouchEvent || disabled_ need handle
1176
1177 // TODO: Region need change to RectList
1178 if (!rect.IsInRegion(parentLocalPoint)) {
1179 return HitTestResult::OUT_OF_REGION;
1180 }
1181
1182 bool preventBubbling = false;
1183
1184 const auto localPoint = parentLocalPoint - rect.GetOffset();
1185 const auto& children = GetChildren();
1186 for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
1187 auto& child = *iter;
1188 auto childHitResult = child->AxisTest(globalPoint, localPoint, onAxisResult);
1189 if (childHitResult == HitTestResult::STOP_BUBBLING) {
1190 preventBubbling = true;
1191 }
1192 // In normal process, the node block the brother node.
1193 if (childHitResult == HitTestResult::BUBBLING) {
1194 // TODO: add hit test mode judge.
1195 break;
1196 }
1197 }
1198
1199 AxisTestResult axisResult;
1200 bool isPrevent = false;
1201 auto inputHub = eventHub_->GetInputEventHub();
1202 if (inputHub) {
1203 const auto coordinateOffset = globalPoint - localPoint;
1204 isPrevent = inputHub->ProcessAxisTestHit(coordinateOffset, axisResult);
1205 }
1206
1207 if (!preventBubbling) {
1208 preventBubbling = isPrevent;
1209 onAxisResult.splice(onAxisResult.end(), std::move(axisResult));
1210 }
1211 if (preventBubbling) {
1212 return HitTestResult::STOP_BUBBLING;
1213 }
1214 return HitTestResult::BUBBLING;
1215 }
1216
AnimateHoverEffect(bool isHovered) const1217 void FrameNode::AnimateHoverEffect(bool isHovered) const
1218 {
1219 auto renderContext = GetRenderContext();
1220 if (!renderContext) {
1221 return;
1222 }
1223 HoverEffectType animationType = HoverEffectType::UNKNOWN;
1224 auto inputEventHub = eventHub_->GetInputEventHub();
1225 if (inputEventHub) {
1226 animationType = inputEventHub->GetHoverEffect();
1227 if (animationType == HoverEffectType::UNKNOWN || animationType == HoverEffectType::AUTO) {
1228 animationType = inputEventHub->GetHoverEffectAuto();
1229 }
1230 }
1231 if (animationType == HoverEffectType::SCALE) {
1232 renderContext->AnimateHoverEffectScale(isHovered);
1233 } else if (animationType == HoverEffectType::BOARD) {
1234 renderContext->AnimateHoverEffectBoard(isHovered);
1235 }
1236 }
1237
GetOrCreateFocusHub() const1238 RefPtr<FocusHub> FrameNode::GetOrCreateFocusHub() const
1239 {
1240 if (!pattern_) {
1241 return eventHub_->GetOrCreateFocusHub();
1242 }
1243 return eventHub_->GetOrCreateFocusHub(pattern_->GetFocusPattern().GetFocusType(),
1244 pattern_->GetFocusPattern().GetFocusable(), pattern_->GetFocusPattern().GetStyleType(),
1245 pattern_->GetFocusPattern().GetFocusPaintParams());
1246 }
1247
OnWindowShow()1248 void FrameNode::OnWindowShow()
1249 {
1250 pattern_->OnWindowShow();
1251 }
1252
OnWindowHide()1253 void FrameNode::OnWindowHide()
1254 {
1255 pattern_->OnWindowHide();
1256 }
1257
OnWindowFocused()1258 void FrameNode::OnWindowFocused()
1259 {
1260 pattern_->OnWindowFocused();
1261 }
1262
OnWindowUnfocused()1263 void FrameNode::OnWindowUnfocused()
1264 {
1265 pattern_->OnWindowUnfocused();
1266 }
1267
GetOffsetRelativeToWindow() const1268 OffsetF FrameNode::GetOffsetRelativeToWindow() const
1269 {
1270 auto offset = geometryNode_->GetFrameOffset();
1271 auto parent = GetAncestorNodeOfFrame();
1272 if (renderContext_ && renderContext_->GetPositionProperty()) {
1273 if (renderContext_->GetPositionProperty()->HasPosition()) {
1274 offset.SetX(static_cast<float>(renderContext_->GetPositionProperty()->GetPosition()->GetX().Value()));
1275 offset.SetY(static_cast<float>(renderContext_->GetPositionProperty()->GetPosition()->GetY().Value()));
1276 }
1277 }
1278 while (parent) {
1279 auto parentRenderContext = parent->GetRenderContext();
1280 if (parentRenderContext && parentRenderContext->GetPositionProperty()) {
1281 if (parentRenderContext->GetPositionProperty()->HasPosition()) {
1282 offset.AddX(
1283 static_cast<float>(parentRenderContext->GetPositionProperty()->GetPosition()->GetX().Value()));
1284 offset.AddY(
1285 static_cast<float>(parentRenderContext->GetPositionProperty()->GetPosition()->GetY().Value()));
1286 parent = parent->GetAncestorNodeOfFrame();
1287 continue;
1288 }
1289 }
1290
1291 offset += parent->geometryNode_->GetFrameOffset();
1292 parent = parent->GetAncestorNodeOfFrame();
1293 }
1294
1295 return offset;
1296 }
1297
GetTransformRectRelativeToWindow() const1298 RectF FrameNode::GetTransformRectRelativeToWindow() const
1299 {
1300 auto context = GetRenderContext();
1301 CHECK_NULL_RETURN(context, RectF());
1302 RectF rect = context->GetPaintRectWithTransform();
1303 auto offset = rect.GetOffset();
1304 auto parent = GetAncestorNodeOfFrame();
1305 while (parent) {
1306 auto parentRenderContext = parent->GetRenderContext();
1307 CHECK_NULL_RETURN(parentRenderContext, rect);
1308 auto parentScale = parentRenderContext->GetTransformScale();
1309 if (parentScale) {
1310 auto oldSize = rect.GetSize();
1311 auto newSize = SizeF(oldSize.Width() * parentScale.value().x, oldSize.Height() * parentScale.value().y);
1312 rect.SetSize(newSize);
1313
1314 offset = OffsetF(offset.GetX() * parentScale.value().x, offset.GetY() * parentScale.value().y);
1315 }
1316
1317 offset += parentRenderContext->GetPaintRectWithTransform().GetOffset();
1318
1319 parent = parent->GetAncestorNodeOfFrame();
1320 }
1321 rect.SetOffset(offset);
1322 return rect;
1323 }
1324
GetTransformRelativeOffset() const1325 OffsetF FrameNode::GetTransformRelativeOffset() const
1326 {
1327 auto context = GetRenderContext();
1328 CHECK_NULL_RETURN(context, OffsetF());
1329 auto offset = context->GetPaintRectWithTransform().GetOffset();
1330 auto parent = GetAncestorNodeOfFrame();
1331
1332 while (parent) {
1333 auto parentRenderContext = parent->GetRenderContext();
1334 offset += parentRenderContext->GetPaintRectWithTransform().GetOffset();
1335 parent = parent->GetAncestorNodeOfFrame();
1336 }
1337
1338 return offset;
1339 }
1340
GetPaintRectOffset() const1341 OffsetF FrameNode::GetPaintRectOffset() const
1342 {
1343 auto context = GetRenderContext();
1344 CHECK_NULL_RETURN(context, OffsetF());
1345 auto offset = context->GetPaintRectWithTransform().GetOffset();
1346 auto parent = GetAncestorNodeOfFrame();
1347 while (parent) {
1348 auto renderContext = parent->GetRenderContext();
1349 CHECK_NULL_RETURN(renderContext, OffsetF());
1350 offset += renderContext->GetPaintRectWithTransform().GetOffset();
1351 parent = parent->GetAncestorNodeOfFrame();
1352 }
1353 return offset;
1354 }
1355
GetPaintRectOffsetToPage() const1356 OffsetF FrameNode::GetPaintRectOffsetToPage() const
1357 {
1358 auto context = GetRenderContext();
1359 CHECK_NULL_RETURN(context, OffsetF());
1360 OffsetF offset = context->GetPaintRectWithTransform().GetOffset();
1361 auto parent = GetAncestorNodeOfFrame();
1362 while (parent && parent->GetTag() != V2::PAGE_ETS_TAG) {
1363 auto renderContext = parent->GetRenderContext();
1364 CHECK_NULL_RETURN(renderContext, OffsetF());
1365 offset += renderContext->GetPaintRectWithTransform().GetOffset();
1366 parent = parent->GetAncestorNodeOfFrame();
1367 }
1368 return (parent && parent->GetTag() == V2::PAGE_ETS_TAG) ? offset : OffsetF();
1369 }
1370
OnNotifyMemoryLevel(int32_t level)1371 void FrameNode::OnNotifyMemoryLevel(int32_t level)
1372 {
1373 pattern_->OnNotifyMemoryLevel(level);
1374 }
1375
GetAllDepthChildrenCount()1376 int32_t FrameNode::GetAllDepthChildrenCount()
1377 {
1378 int32_t result = 0;
1379 std::list<RefPtr<FrameNode>> children;
1380 children.emplace_back(Claim(this));
1381 while (!children.empty()) {
1382 auto& node = children.front();
1383 if (!node->IsInternal()) {
1384 result++;
1385 node->GenerateOneDepthVisibleFrame(children);
1386 }
1387 children.pop_front();
1388 }
1389 return result;
1390 }
1391
OnAccessibilityEvent(AccessibilityEventType eventType) const1392 void FrameNode::OnAccessibilityEvent(AccessibilityEventType eventType) const
1393 {
1394 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
1395 AccessibilityEvent event;
1396 event.type = eventType;
1397 event.nodeId = GetAccessibilityId();
1398 PipelineContext::GetCurrentContext()->SendEventToAccessibility(event);
1399 }
1400 }
1401
AddHotZoneRect(const DimensionRect & hotZoneRect) const1402 void FrameNode::AddHotZoneRect(const DimensionRect& hotZoneRect) const
1403 {
1404 auto gestureHub = GetOrCreateGestureEventHub();
1405 gestureHub->AddResponseRect(hotZoneRect);
1406 }
1407
RemoveLastHotZoneRect() const1408 void FrameNode::RemoveLastHotZoneRect() const
1409 {
1410 auto gestureHub = GetOrCreateGestureEventHub();
1411 gestureHub->RemoveLastResponseRect();
1412 }
1413
1414 } // namespace OHOS::Ace::NG
1415