• 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/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