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/dimension.h"
19 #include "base/geometry/ng/point_t.h"
20 #include "base/log/ace_trace.h"
21 #include "base/log/dump_log.h"
22 #include "base/memory/ace_type.h"
23 #include "base/memory/referenced.h"
24 #include "base/thread/cancelable_callback.h"
25 #include "base/thread/task_executor.h"
26 #include "base/utils/system_properties.h"
27 #include "base/utils/time_util.h"
28 #include "base/utils/utils.h"
29 #include "core/common/ace_application_info.h"
30 #include "core/components/common/layout/constants.h"
31 #include "core/components_ng/base/inspector.h"
32 #include "core/components_ng/base/ui_node.h"
33 #include "core/components_ng/event/gesture_event_hub.h"
34 #include "core/components_ng/layout/layout_algorithm.h"
35 #include "core/components_ng/layout/layout_wrapper.h"
36 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
37 #include "core/components_ng/pattern/pattern.h"
38 #include "core/components_ng/property/measure_property.h"
39 #include "core/components_ng/property/measure_utils.h"
40 #include "core/components_ng/property/property.h"
41 #include "core/components_ng/render/paint_wrapper.h"
42 #include "core/components_ng/syntax/lazy_for_each_node.h"
43 #include "core/components_v2/inspector/inspector_constants.h"
44 #include "core/event/touch_event.h"
45 #include "core/pipeline_ng/pipeline_context.h"
46 #include "core/pipeline_ng/ui_task_scheduler.h"
47
48 namespace {
49 constexpr double VISIBLE_RATIO_MIN = 0.0;
50 constexpr double VISIBLE_RATIO_MAX = 1.0;
51 #if defined(PREVIEW)
52 constexpr int32_t SUBSTR_LENGTH = 3;
53 const char DIMENSION_UNIT_VP[] = "vp";
54 #endif
55 } // namespace
56 namespace OHOS::Ace::NG {
57
58 class FramePorxy {
59 public:
60 struct FrameChildNode {
61 RefPtr<UINode> node;
62 uint32_t startIndex = 0;
63 uint32_t count = 0;
64 };
65
FramePorxy(FrameNode * frameNode)66 explicit FramePorxy(FrameNode* frameNode) : hostNode_(frameNode) {}
67
Build()68 void Build()
69 {
70 if (hostNode_ == nullptr || !children_.empty()) {
71 return;
72 }
73 totalCount_ = 0;
74 auto children = hostNode_->GetChildren();
75 int32_t startIndex = 0;
76 int32_t count = 0;
77 for (const auto& child : children) {
78 count = child->FrameCount();
79 children_.push_back({ child, startIndex, count });
80 startIndex += count;
81 totalCount_ += count;
82 }
83 cursor_ = children_.begin();
84 }
85
AddFrameNode(const RefPtr<UINode> & UiNode,std::list<RefPtr<LayoutWrapper>> & allFrameNodeChildren,std::map<uint32_t,RefPtr<LayoutWrapper>> & partFrameNodeChildren,uint32_t & count)86 static void AddFrameNode(const RefPtr<UINode>& UiNode, std::list<RefPtr<LayoutWrapper>>& allFrameNodeChildren,
87 std::map<uint32_t, RefPtr<LayoutWrapper>>& partFrameNodeChildren, uint32_t& count)
88 {
89 auto frameNode = AceType::DynamicCast<FrameNode>(UiNode);
90 if (frameNode) {
91 allFrameNodeChildren.emplace_back(frameNode);
92 partFrameNodeChildren[count++] = frameNode;
93 return;
94 }
95 auto lazyForEachNode = AceType::DynamicCast<LazyForEachNode>(UiNode);
96 if (lazyForEachNode) {
97 lazyForEachNode->BuildAllChildren();
98 } else {
99 auto customNode = AceType::DynamicCast<CustomNode>(UiNode);
100 if (customNode) {
101 customNode->Render();
102 }
103 }
104 for (const auto& child : UiNode->GetChildren()) {
105 auto frameNode = AceType::DynamicCast<FrameNode>(child);
106 if (frameNode) {
107 allFrameNodeChildren.emplace_back(frameNode);
108 partFrameNodeChildren[count++] = frameNode;
109 continue;
110 }
111 AddFrameNode(child, allFrameNodeChildren, partFrameNodeChildren, count);
112 }
113 }
114
GetAllFrameChildren()115 std::list<RefPtr<LayoutWrapper>>& GetAllFrameChildren()
116 {
117 if (!allFrameNodeChildren_.empty()) {
118 return allFrameNodeChildren_;
119 }
120 Build();
121 uint32_t count = 0;
122 for (const auto& child : children_) {
123 AddFrameNode(child.node, allFrameNodeChildren_, partFrameNodeChildren_, count);
124 }
125 return allFrameNodeChildren_;
126 }
127
FindFrameNodeByIndex(uint32_t index,bool needBuild)128 RefPtr<LayoutWrapper> FindFrameNodeByIndex(uint32_t index, bool needBuild)
129 {
130 while (cursor_ != children_.end()) {
131 if (cursor_->startIndex > index) {
132 cursor_--;
133 continue;
134 }
135
136 if (cursor_->startIndex + cursor_->count > index) {
137 auto frameNode = AceType::DynamicCast<FrameNode>(
138 cursor_->node->GetFrameChildByIndex(index - cursor_->startIndex, needBuild));
139 return frameNode;
140 }
141 cursor_++;
142 if (cursor_ == children_.end()) {
143 cursor_ = children_.begin();
144 return nullptr;
145 }
146 }
147 return nullptr;
148 }
149
GetFrameNodeByIndex(uint32_t index,bool needBuild)150 RefPtr<LayoutWrapper> GetFrameNodeByIndex(uint32_t index, bool needBuild)
151 {
152 auto itor = partFrameNodeChildren_.find(index);
153 if (itor == partFrameNodeChildren_.end()) {
154 Build();
155 auto child = FindFrameNodeByIndex(index, needBuild);
156 if (child) {
157 partFrameNodeChildren_[index] = child;
158 return child;
159 }
160 return nullptr;
161 }
162 return itor->second;
163 }
164
ResetChildren(bool needResetChild=false)165 void ResetChildren(bool needResetChild = false)
166 {
167 allFrameNodeChildren_.clear();
168 partFrameNodeChildren_.clear();
169 totalCount_ = 0;
170 if (needResetChild) {
171 children_.clear();
172 cursor_ = children_.begin();
173 }
174 }
175
RemoveChildInRenderTree(uint32_t index)176 void RemoveChildInRenderTree(uint32_t index)
177 {
178 auto itor = partFrameNodeChildren_.find(index);
179 if (itor == partFrameNodeChildren_.end()) {
180 return;
181 }
182 itor->second->SetActive(false);
183 partFrameNodeChildren_.erase(itor);
184 while (cursor_ != children_.end()) {
185 if (cursor_->startIndex > index) {
186 cursor_--;
187 continue;
188 }
189 if (cursor_->startIndex + cursor_->count > index) {
190 cursor_->node->DoRemoveChildInRenderTree(index - cursor_->startIndex);
191 return;
192 }
193 cursor_++;
194 if (cursor_ == children_.end()) {
195 cursor_ = children_.begin();
196 return;
197 }
198 }
199 }
200
RemoveAllChildInRenderTree()201 void RemoveAllChildInRenderTree()
202 {
203 SetAllChildrenInActive();
204 ResetChildren();
205 Build();
206 for (const auto& child : children_) {
207 child.node->DoRemoveChildInRenderTree(0, true);
208 }
209 }
210
GetTotalCount()211 uint32_t GetTotalCount()
212 {
213 return totalCount_;
214 }
215
SetAllChildrenInActive()216 void SetAllChildrenInActive()
217 {
218 for (const auto& child : partFrameNodeChildren_) {
219 child.second->SetActive(false);
220 }
221 }
222
Dump()223 std::string Dump()
224 {
225 std::string info = "FrameChildNode:[";
226 for (const auto& child : children_) {
227 info += std::to_string(child.node->GetId());
228 info += "-";
229 info += std::to_string(child.startIndex);
230 info += "-";
231 info += std::to_string(child.count);
232 info += ",";
233 }
234 info += "] partFrameNodeChildren:[";
235 for (const auto& child : partFrameNodeChildren_) {
236 info += std::to_string(child.second->GetHostNode()->GetId());
237 info += ",";
238 }
239 info += "] TotalCount:";
240 info += std::to_string(totalCount_);
241 return info;
242 }
243
SetCacheCount(int32_t cacheCount,const std::optional<LayoutConstraintF> & itemConstraint)244 void SetCacheCount(int32_t cacheCount, const std::optional<LayoutConstraintF>& itemConstraint)
245 {
246 for (const auto& child : children_) {
247 child.node->OnSetCacheCount(cacheCount, itemConstraint);
248 }
249 }
250
251 private:
252 std::list<FrameChildNode> children_;
253 std::list<FrameChildNode>::iterator cursor_ = children_.begin();
254 std::list<RefPtr<LayoutWrapper>> allFrameNodeChildren_;
255 std::map<uint32_t, RefPtr<LayoutWrapper>> partFrameNodeChildren_;
256 uint32_t totalCount_ = 0;
257 FrameNode* hostNode_ { nullptr };
258 }; // namespace OHOS::Ace::NG
259
FrameNode(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern,bool isRoot)260 FrameNode::FrameNode(const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern, bool isRoot)
261 : UINode(tag, nodeId, isRoot), LayoutWrapper(WeakClaim(this)), pattern_(pattern),
262 frameProxy_(std::make_unique<FramePorxy>(this))
263 {
264 renderContext_->InitContext(IsRootNode(), pattern_->GetContextParam());
265 paintProperty_ = pattern->CreatePaintProperty();
266 layoutProperty_ = pattern->CreateLayoutProperty();
267 eventHub_ = pattern->CreateEventHub();
268 accessibilityProperty_ = pattern->CreateAccessibilityProperty();
269 // first create make layout property dirty.
270 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
271 layoutProperty_->SetHost(WeakClaim(this));
272 }
273
~FrameNode()274 FrameNode::~FrameNode()
275 {
276 for (const auto& destroyCallback : destroyCallbacks_) {
277 destroyCallback();
278 }
279
280 pattern_->DetachFromFrameNode(this);
281 if (IsOnMainTree()) {
282 OnDetachFromMainTree(false);
283 }
284 TriggerVisibleAreaChangeCallback(true);
285 visibleAreaUserCallbacks_.clear();
286 visibleAreaInnerCallbacks_.clear();
287 auto pipeline = PipelineContext::GetCurrentContext();
288 if (pipeline) {
289 pipeline->RemoveOnAreaChangeNode(GetId());
290 pipeline->RemoveVisibleAreaChangeNode(GetId());
291 pipeline->ChangeMouseStyle(GetId(), MouseFormat::DEFAULT);
292 pipeline->FreeMouseStyleHoldNode(GetId());
293 pipeline->RemoveStoredNode(GetRestoreId());
294 auto dragManager = pipeline->GetDragDropManager();
295 if (dragManager) {
296 dragManager->RemoveDragFrameNode(GetId());
297 }
298 }
299 }
300
CreateFrameNodeWithTree(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern)301 RefPtr<FrameNode> FrameNode::CreateFrameNodeWithTree(
302 const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern)
303 {
304 auto newChild = CreateFrameNode(tag, nodeId, pattern, true);
305 newChild->SetDepth(1);
306 return newChild;
307 }
308
GetOrCreateFrameNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)309 RefPtr<FrameNode> FrameNode::GetOrCreateFrameNode(
310 const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
311 {
312 auto frameNode = GetFrameNode(tag, nodeId);
313 if (frameNode) {
314 return frameNode;
315 }
316 auto pattern = patternCreator ? patternCreator() : MakeRefPtr<Pattern>();
317 return CreateFrameNode(tag, nodeId, pattern);
318 }
319
GetFrameNode(const std::string & tag,int32_t nodeId)320 RefPtr<FrameNode> FrameNode::GetFrameNode(const std::string& tag, int32_t nodeId)
321 {
322 auto frameNode = ElementRegister::GetInstance()->GetSpecificItemById<FrameNode>(nodeId);
323 CHECK_NULL_RETURN_NOLOG(frameNode, nullptr);
324 if (frameNode->GetTag() != tag) {
325 LOGE("the tag is changed");
326 ElementRegister::GetInstance()->RemoveItemSilently(nodeId);
327 auto parent = frameNode->GetParent();
328 if (parent) {
329 parent->RemoveChild(frameNode);
330 }
331 return nullptr;
332 }
333 return frameNode;
334 }
335
CreateFrameNode(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern,bool isRoot)336 RefPtr<FrameNode> FrameNode::CreateFrameNode(
337 const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern, bool isRoot)
338 {
339 auto frameNode = MakeRefPtr<FrameNode>(tag, nodeId, pattern, isRoot);
340 frameNode->InitializePatternAndContext();
341 ElementRegister::GetInstance()->AddUINode(frameNode);
342 return frameNode;
343 }
344
ProcessOffscreenNode(const RefPtr<FrameNode> & node)345 void FrameNode::ProcessOffscreenNode(const RefPtr<FrameNode>& node)
346 {
347 CHECK_NULL_VOID(node);
348 node->ProcessOffscreenTask();
349 node->MarkModifyDone();
350 node->UpdateLayoutPropertyFlag();
351 node->SetActive();
352 node->isLayoutDirtyMarked_ = true;
353 node->CreateLayoutTask();
354
355 auto paintProperty = node->GetPaintProperty<PaintProperty>();
356 auto wrapper = node->CreatePaintWrapper();
357 if (wrapper != nullptr) {
358 wrapper->FlushRender();
359 }
360 paintProperty->CleanDirty();
361 auto pipeline = PipelineContext::GetCurrentContext();
362 CHECK_NULL_VOID(pipeline);
363 pipeline->FlushMessages();
364 node->SetActive(false);
365 }
366
InitializePatternAndContext()367 void FrameNode::InitializePatternAndContext()
368 {
369 eventHub_->AttachHost(WeakClaim(this));
370 pattern_->AttachToFrameNode(WeakClaim(this));
371 accessibilityProperty_->SetHost(WeakClaim(this));
372 renderContext_->SetRequestFrame([weak = WeakClaim(this)] {
373 auto frameNode = weak.Upgrade();
374 CHECK_NULL_VOID(frameNode);
375 if (frameNode->IsOnMainTree()) {
376 auto context = frameNode->GetContext();
377 CHECK_NULL_VOID(context);
378 context->RequestFrame();
379 return;
380 }
381 frameNode->hasPendingRequest_ = true;
382 });
383 renderContext_->SetHostNode(WeakClaim(this));
384 // Initialize FocusHub
385 if (pattern_->GetFocusPattern().GetFocusType() != FocusType::DISABLE) {
386 GetOrCreateFocusHub();
387 }
388 }
389
DumpOverlayInfo()390 void FrameNode::DumpOverlayInfo()
391 {
392 if (!layoutProperty_->IsOverlayNode()) {
393 return;
394 }
395 DumpLog::GetInstance().AddDesc(std::string("IsOverlayNode: ").append(std::string("true")));
396 Dimension offsetX, offsetY;
397 layoutProperty_->GetOverlayOffset(offsetX, offsetY);
398 DumpLog::GetInstance().AddDesc(
399 std::string("OverlayOffset: ").append(offsetX.ToString()).append(std::string(", ")).append(offsetY.ToString()));
400 }
401
DumpInfo()402 void FrameNode::DumpInfo()
403 {
404 DumpLog::GetInstance().AddDesc(std::string("FrameRect: ").append(geometryNode_->GetFrameRect().ToString()));
405 DumpLog::GetInstance().AddDesc(
406 std::string("BackgroundColor: ").append(renderContext_->GetBackgroundColor()->ColorToString()));
407 DumpLog::GetInstance().AddDesc(std::string("ParentLayoutConstraint: ")
408 .append(geometryNode_->GetParentLayoutConstraint().has_value()
409 ? geometryNode_->GetParentLayoutConstraint().value().ToString()
410 : "NA"));
411 DumpLog::GetInstance().AddDesc(std::string("top: ")
412 .append(std::to_string(GetOffsetRelativeToWindow().GetY()))
413 .append(" left: ")
414 .append(std::to_string(GetOffsetRelativeToWindow().GetX())));
415 DumpLog::GetInstance().AddDesc(std::string("Active: ").append(std::to_string(static_cast<int32_t>(IsActive()))));
416 DumpLog::GetInstance().AddDesc(std::string("Visible: ")
417 .append(std::to_string(static_cast<int32_t>(
418 layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)))));
419 if (layoutProperty_->GetPaddingProperty()) {
420 DumpLog::GetInstance().AddDesc(
421 std::string("Padding: ").append(layoutProperty_->GetPaddingProperty()->ToString().c_str()));
422 }
423 if (layoutProperty_->GetBorderWidthProperty()) {
424 DumpLog::GetInstance().AddDesc(
425 std::string("Border: ").append(layoutProperty_->GetBorderWidthProperty()->ToString().c_str()));
426 }
427 if (layoutProperty_->GetMarginProperty()) {
428 DumpLog::GetInstance().AddDesc(
429 std::string("Margin: ").append(layoutProperty_->GetMarginProperty()->ToString().c_str()));
430 }
431 if (layoutProperty_->GetCalcLayoutConstraint()) {
432 DumpLog::GetInstance().AddDesc(std::string("User defined constraint: ")
433 .append(layoutProperty_->GetCalcLayoutConstraint()->ToString().c_str()));
434 }
435 DumpLog::GetInstance().AddDesc(std::string("compid: ").append(propInspectorId_.value_or("")));
436 DumpLog::GetInstance().AddDesc(std::string("ContentConstraint: ")
437 .append(layoutProperty_->GetContentLayoutConstraint().has_value()
438 ? layoutProperty_->GetContentLayoutConstraint().value().ToString()
439 : "NA"));
440 DumpOverlayInfo();
441 DumpLog::GetInstance().AddDesc(
442 std::string("PaintRect: ").append(renderContext_->GetPaintRectWithTransform().ToString()));
443 DumpLog::GetInstance().AddDesc(std::string("FrameProxy: ").append(frameProxy_->Dump().c_str()));
444 if (pattern_) {
445 pattern_->DumpInfo();
446 }
447 if (renderContext_) {
448 renderContext_->DumpInfo();
449 }
450 }
451
FocusToJsonValue(std::unique_ptr<JsonValue> & json) const452 void FrameNode::FocusToJsonValue(std::unique_ptr<JsonValue>& json) const
453 {
454 bool enabled = true;
455 bool focusable = false;
456 bool focused = false;
457 bool defaultFocus = false;
458 bool groupDefaultFocus = false;
459 bool focusOnTouch = false;
460 int32_t tabIndex = 0;
461 auto focusHub = GetFocusHub();
462 if (focusHub) {
463 enabled = focusHub->IsEnabled();
464 focusable = focusHub->IsFocusable();
465 focused = focusHub->IsCurrentFocus();
466 defaultFocus = focusHub->IsDefaultFocus();
467 groupDefaultFocus = focusHub->IsDefaultGroupFocus();
468 focusOnTouch = focusHub->IsFocusOnTouch().value_or(false);
469 tabIndex = focusHub->GetTabIndex();
470 }
471 json->Put("enabled", enabled);
472 json->Put("focusable", focusable);
473 json->Put("focused", focused);
474 json->Put("defaultFocus", defaultFocus);
475 json->Put("groupDefaultFocus", groupDefaultFocus);
476 json->Put("focusOnTouch", focusOnTouch);
477 json->Put("tabIndex", tabIndex);
478 }
479
MouseToJsonValue(std::unique_ptr<JsonValue> & json) const480 void FrameNode::MouseToJsonValue(std::unique_ptr<JsonValue>& json) const
481 {
482 std::string hoverEffect = "HoverEffect.Auto";
483 auto inputEventHub = GetOrCreateInputEventHub();
484 if (inputEventHub) {
485 hoverEffect = inputEventHub->GetHoverEffectStr();
486 }
487 json->Put("hoverEffect", hoverEffect.c_str());
488 }
489
TouchToJsonValue(std::unique_ptr<JsonValue> & json) const490 void FrameNode::TouchToJsonValue(std::unique_ptr<JsonValue>& json) const
491 {
492 bool touchable = true;
493 std::string hitTestMode = "HitTestMode.Default";
494 auto gestureEventHub = GetOrCreateGestureEventHub();
495 std::vector<DimensionRect> responseRegion;
496 std::vector<DimensionRect> mouseResponseRegion;
497 if (gestureEventHub) {
498 touchable = gestureEventHub->GetTouchable();
499 hitTestMode = gestureEventHub->GetHitTestModeStr();
500 responseRegion = gestureEventHub->GetResponseRegion();
501 mouseResponseRegion = gestureEventHub->GetMouseResponseRegion();
502 }
503 json->Put("touchable", touchable);
504 json->Put("hitTestBehavior", hitTestMode.c_str());
505 auto jsArr = JsonUtil::CreateArray(true);
506 for (int32_t i = 0; i < static_cast<int32_t>(responseRegion.size()); ++i) {
507 auto iStr = std::to_string(i);
508 jsArr->Put(iStr.c_str(), responseRegion[i].ToJsonString().c_str());
509 }
510 json->Put("responseRegion", jsArr);
511 for (int32_t i = 0; i < static_cast<int32_t>(mouseResponseRegion.size()); ++i) {
512 auto iStr = std::to_string(i);
513 jsArr->Put(iStr.c_str(), mouseResponseRegion[i].ToJsonString().c_str());
514 }
515 json->Put("mouseResponseRegion", jsArr);
516 }
517
GeometryNodeToJsonValue(std::unique_ptr<JsonValue> & json) const518 void FrameNode::GeometryNodeToJsonValue(std::unique_ptr<JsonValue>& json) const
519 {
520 #if defined(PREVIEW)
521 bool hasIdealWidth = false;
522 bool hasIdealHeight = false;
523 if (layoutProperty_ && layoutProperty_->GetCalcLayoutConstraint()) {
524 auto selfIdealSize = layoutProperty_->GetCalcLayoutConstraint()->selfIdealSize;
525 hasIdealWidth = selfIdealSize.has_value() && selfIdealSize.value().Width().has_value();
526 hasIdealHeight = selfIdealSize.has_value() && selfIdealSize.value().Height().has_value();
527 }
528
529 auto jsonSize = json->GetValue("size");
530 if (!hasIdealWidth) {
531 auto idealWidthVpStr = std::to_string(Dimension(geometryNode_->GetFrameSize().Width()).ConvertToVp());
532 auto widthStr =
533 (idealWidthVpStr.substr(0, idealWidthVpStr.find(".") + SUBSTR_LENGTH) + DIMENSION_UNIT_VP).c_str();
534 json->Put("width", widthStr);
535 if (jsonSize) {
536 jsonSize->Put("width", widthStr);
537 }
538 }
539
540 if (!hasIdealHeight) {
541 auto idealHeightVpStr = std::to_string(Dimension(geometryNode_->GetFrameSize().Height()).ConvertToVp());
542 auto heightStr =
543 (idealHeightVpStr.substr(0, idealHeightVpStr.find(".") + SUBSTR_LENGTH) + DIMENSION_UNIT_VP).c_str();
544 json->Put("height", heightStr);
545 if (jsonSize) {
546 jsonSize->Put("height", heightStr);
547 }
548 }
549 #endif
550 }
551
ToJsonValue(std::unique_ptr<JsonValue> & json) const552 void FrameNode::ToJsonValue(std::unique_ptr<JsonValue>& json) const
553 {
554 if (renderContext_) {
555 renderContext_->ToJsonValue(json);
556 }
557 // scrollable in AccessibilityProperty
558 ACE_PROPERTY_TO_JSON_VALUE(accessibilityProperty_, AccessibilityProperty);
559 ACE_PROPERTY_TO_JSON_VALUE(layoutProperty_, LayoutProperty);
560 ACE_PROPERTY_TO_JSON_VALUE(paintProperty_, PaintProperty);
561 ACE_PROPERTY_TO_JSON_VALUE(pattern_, Pattern);
562 if (eventHub_) {
563 eventHub_->ToJsonValue(json);
564 }
565 FocusToJsonValue(json);
566 MouseToJsonValue(json);
567 TouchToJsonValue(json);
568 GeometryNodeToJsonValue(json);
569 json->Put("id", propInspectorId_.value_or("").c_str());
570 }
571
FromJson(const std::unique_ptr<JsonValue> & json)572 void FrameNode::FromJson(const std::unique_ptr<JsonValue>& json)
573 {
574 if (renderContext_) {
575 LOGD("UITree start decode renderContext");
576 renderContext_->FromJson(json);
577 }
578 LOGD("UITree start decode accessibilityProperty");
579 accessibilityProperty_->FromJson(json);
580 LOGD("UITree start decode layoutProperty");
581 layoutProperty_->FromJson(json);
582 LOGD("UITree start decode paintProperty");
583 paintProperty_->FromJson(json);
584 LOGD("UITree start decode pattern");
585 pattern_->FromJson(json);
586 if (eventHub_) {
587 LOGD("UITree start decode eventHub");
588 eventHub_->FromJson(json);
589 }
590 }
591
OnAttachToMainTree(bool recursive)592 void FrameNode::OnAttachToMainTree(bool recursive)
593 {
594 eventHub_->FireOnAppear();
595 renderContext_->OnNodeAppear(recursive);
596 if (IsResponseRegion() || HasPositionProp()) {
597 auto parent = GetParent();
598 while (parent) {
599 auto frameNode = AceType::DynamicCast<FrameNode>(parent);
600 if (frameNode) {
601 frameNode->MarkResponseRegion(true);
602 }
603 parent = parent->GetParent();
604 }
605 }
606 // node may have been measured before AttachToMainTree
607 if (geometryNode_->GetParentLayoutConstraint().has_value() && !UseOffscreenProcess()) {
608 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE_SELF);
609 }
610
611 UINode::OnAttachToMainTree(recursive);
612
613 if (!hasPendingRequest_) {
614 return;
615 }
616 auto context = GetContext();
617 CHECK_NULL_VOID(context);
618 context->RequestFrame();
619 hasPendingRequest_ = false;
620 }
621
OnConfigurationUpdate(const OnConfigurationChange & configurationChange)622 void FrameNode::OnConfigurationUpdate(const OnConfigurationChange& configurationChange)
623 {
624 if (configurationChange.languageUpdate) {
625 pattern_->OnLanguageConfigurationUpdate();
626 MarkModifyDone();
627 MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
628 }
629 if (configurationChange.colorModeUpdate) {
630 pattern_->OnColorConfigurationUpdate();
631 MarkModifyDone();
632 MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
633 }
634 }
635
OnVisibleChange(bool isVisible)636 void FrameNode::OnVisibleChange(bool isVisible)
637 {
638 pattern_->OnVisibleChange(isVisible);
639 UpdateChildrenVisible(isVisible);
640 TriggerVisibleAreaChangeCallback(true);
641 }
642
OnDetachFromMainTree(bool recursive)643 void FrameNode::OnDetachFromMainTree(bool recursive)
644 {
645 eventHub_->FireOnDisappear();
646 renderContext_->OnNodeDisappear(recursive);
647 }
648
SwapDirtyLayoutWrapperOnMainThread(const RefPtr<LayoutWrapper> & dirty)649 void FrameNode::SwapDirtyLayoutWrapperOnMainThread(const RefPtr<LayoutWrapper>& dirty)
650 {
651 LOGD("SwapDirtyLayoutWrapperOnMainThread, %{public}s", GetTag().c_str());
652 CHECK_NULL_VOID(dirty);
653
654 // update new layout constrain.
655 layoutProperty_->UpdateLayoutConstraint(dirty->GetLayoutProperty());
656
657 // active change flag judge.
658 SetActive(dirty->IsActive());
659 if (!isActive_) {
660 LOGD("current node is inactive, don't need to render");
661 return;
662 }
663
664 // update layout size.
665 bool frameSizeChange = geometryNode_->GetFrameSize() != dirty->GetGeometryNode()->GetFrameSize();
666 bool frameOffsetChange = geometryNode_->GetFrameOffset() != dirty->GetGeometryNode()->GetFrameOffset();
667 bool contentSizeChange = geometryNode_->GetContentSize() != dirty->GetGeometryNode()->GetContentSize();
668 bool contentOffsetChange = geometryNode_->GetContentOffset() != dirty->GetGeometryNode()->GetContentOffset();
669
670 SetGeometryNode(dirty->GetGeometryNode());
671
672 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
673 if (geometryTransition != nullptr && geometryTransition->IsRunning()) {
674 geometryTransition->DidLayout(dirty);
675 } else if (frameSizeChange || frameOffsetChange || HasPositionProp() ||
676 (pattern_->GetContextParam().has_value() && contentSizeChange)) {
677 renderContext_->SyncGeometryProperties(RawPtr(dirty->GetGeometryNode()));
678 }
679
680 // clean layout flag.
681 layoutProperty_->CleanDirty();
682 DirtySwapConfig config { frameSizeChange, frameOffsetChange, contentSizeChange, contentOffsetChange };
683 // check if need to paint content.
684 auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
685 CHECK_NULL_VOID(layoutAlgorithmWrapper);
686 config.skipMeasure = layoutAlgorithmWrapper->SkipMeasure() || dirty->SkipMeasureContent();
687 config.skipLayout = layoutAlgorithmWrapper->SkipLayout();
688 if ((config.skipMeasure == false) && (config.skipLayout == false) && GetInspectorId().has_value()) {
689 auto pipeline = PipelineContext::GetCurrentContext();
690 CHECK_NULL_VOID(pipeline);
691 pipeline->OnLayoutCompleted(GetInspectorId()->c_str());
692 }
693 auto needRerender = pattern_->OnDirtyLayoutWrapperSwap(dirty, config);
694 // TODO: temp use and need to delete.
695 needRerender = needRerender || pattern_->OnDirtyLayoutWrapperSwap(dirty, config.skipMeasure, config.skipLayout);
696 if (needRerender || CheckNeedRender(paintProperty_->GetPropertyChangeFlag())) {
697 MarkDirtyNode(true, true, PROPERTY_UPDATE_RENDER);
698 }
699
700 // update border.
701 if (layoutProperty_->GetBorderWidthProperty()) {
702 if (!renderContext_->HasBorderColor()) {
703 BorderColorProperty borderColorProperty;
704 borderColorProperty.SetColor(Color::BLACK);
705 renderContext_->UpdateBorderColor(borderColorProperty);
706 }
707 if (!renderContext_->HasBorderStyle()) {
708 BorderStyleProperty borderStyleProperty;
709 borderStyleProperty.SetBorderStyle(BorderStyle::SOLID);
710 renderContext_->UpdateBorderStyle(borderStyleProperty);
711 }
712 if (layoutProperty_->GetLayoutConstraint().has_value()) {
713 renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
714 ScaleProperty::CreateScaleProperty(),
715 layoutProperty_->GetLayoutConstraint()->percentReference.Width()));
716 } else {
717 renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
718 ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth()));
719 }
720 }
721
722 // update background
723 if (builderFunc_) {
724 auto builderNode = builderFunc_();
725 auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
726 AceType::MakeRefPtr<LinearLayoutPattern>(true));
727 builderNode->MountToParent(columnNode);
728 SetBackgroundLayoutConstraint(columnNode);
729 renderContext_->CreateBackgroundPixelMap(columnNode);
730 builderFunc_ = nullptr;
731 backgroundNode_ = columnNode;
732 }
733
734 // update focus state
735 auto focusHub = GetFocusHub();
736 if (focusHub && focusHub->IsCurrentFocus()) {
737 focusHub->ClearFocusState(false);
738 focusHub->PaintFocusState(false);
739 }
740
741 // rebuild child render node.
742 RebuildRenderContextTree();
743 }
744
SetBackgroundLayoutConstraint(const RefPtr<FrameNode> & customNode)745 void FrameNode::SetBackgroundLayoutConstraint(const RefPtr<FrameNode>& customNode)
746 {
747 CHECK_NULL_VOID(customNode);
748 LayoutConstraintF layoutConstraint;
749 layoutConstraint.scaleProperty = ScaleProperty::CreateScaleProperty();
750 layoutConstraint.percentReference.SetWidth(geometryNode_->GetFrameSize().Width());
751 layoutConstraint.percentReference.SetHeight(geometryNode_->GetFrameSize().Height());
752 layoutConstraint.maxSize.SetWidth(geometryNode_->GetFrameSize().Width());
753 layoutConstraint.maxSize.SetHeight(geometryNode_->GetFrameSize().Height());
754 customNode->GetGeometryNode()->SetParentLayoutConstraint(layoutConstraint);
755 }
756
AdjustGridOffset()757 void FrameNode::AdjustGridOffset()
758 {
759 if (!isActive_) {
760 return;
761 }
762 if (layoutProperty_->UpdateGridOffset(Claim(this))) {
763 renderContext_->UpdateOffset(OffsetT<Dimension>());
764 renderContext_->UpdateAnchor(OffsetT<Dimension>());
765 renderContext_->SyncGeometryProperties(RawPtr(GetGeometryNode()));
766 }
767 }
768
ClearUserOnAreaChange()769 void FrameNode::ClearUserOnAreaChange()
770 {
771 if (eventHub_) {
772 eventHub_->ClearUserOnAreaChanged();
773 }
774 }
775
SetOnAreaChangeCallback(OnAreaChangedFunc && callback)776 void FrameNode::SetOnAreaChangeCallback(OnAreaChangedFunc&& callback)
777 {
778 if (!lastFrameRect_) {
779 lastFrameRect_ = std::make_unique<RectF>();
780 }
781 if (!lastParentOffsetToWindow_) {
782 lastParentOffsetToWindow_ = std::make_unique<OffsetF>();
783 }
784 eventHub_->SetOnAreaChanged(std::move(callback));
785 }
786
TriggerOnAreaChangeCallback()787 void FrameNode::TriggerOnAreaChangeCallback()
788 {
789 if (eventHub_->HasOnAreaChanged() && lastFrameRect_ && lastParentOffsetToWindow_) {
790 auto currFrameRect = geometryNode_->GetFrameRect();
791 auto currParentOffsetToWindow = GetOffsetRelativeToWindow() - currFrameRect.GetOffset();
792 if (currFrameRect != *lastFrameRect_ || currParentOffsetToWindow != *lastParentOffsetToWindow_) {
793 eventHub_->FireOnAreaChanged(
794 *lastFrameRect_, *lastParentOffsetToWindow_, currFrameRect, currParentOffsetToWindow);
795 *lastFrameRect_ = currFrameRect;
796 *lastParentOffsetToWindow_ = currParentOffsetToWindow;
797 }
798 }
799 pattern_->OnAreaChangedInner();
800 }
801
TriggerVisibleAreaChangeCallback(bool forceDisappear)802 void FrameNode::TriggerVisibleAreaChangeCallback(bool forceDisappear)
803 {
804 auto context = PipelineContext::GetCurrentContext();
805 CHECK_NULL_VOID(context);
806
807 bool isFrameDisappear = forceDisappear || !context->GetOnShow() || !IsOnMainTree();
808 if (!isFrameDisappear) {
809 bool curFrameIsActive = isActive_;
810 bool curIsVisible = IsVisible();
811 auto parent = GetParent();
812 while (parent) {
813 auto parentFrame = AceType::DynamicCast<FrameNode>(parent);
814 if (!parentFrame) {
815 parent = parent->GetParent();
816 continue;
817 }
818 if (!parentFrame->isActive_) {
819 curFrameIsActive = false;
820 break;
821 }
822 if (!parentFrame->IsVisible()) {
823 curIsVisible = false;
824 break;
825 }
826 parent = parent->GetParent();
827 }
828 isFrameDisappear = !curIsVisible || !curFrameIsActive;
829 }
830
831 if (isFrameDisappear) {
832 if (!NearEqual(lastVisibleRatio_, VISIBLE_RATIO_MIN)) {
833 ProcessAllVisibleCallback(visibleAreaUserCallbacks_, VISIBLE_RATIO_MIN);
834 ProcessAllVisibleCallback(visibleAreaInnerCallbacks_, VISIBLE_RATIO_MIN);
835 lastVisibleRatio_ = VISIBLE_RATIO_MIN;
836 }
837 return;
838 }
839
840 auto frameRect = renderContext_->GetPaintRectWithTransform();
841 frameRect.SetOffset(GetOffsetRelativeToWindow());
842 auto visibleRect = frameRect;
843 RectF parentRect;
844 auto parentUi = GetParent();
845 if (!parentUi) {
846 visibleRect.SetWidth(0.0f);
847 visibleRect.SetHeight(0.0f);
848 }
849 while (parentUi) {
850 auto parentFrame = AceType::DynamicCast<FrameNode>(parentUi);
851 if (!parentFrame) {
852 parentUi = parentUi->GetParent();
853 continue;
854 }
855 parentRect = parentFrame->GetRenderContext()->GetPaintRectWithTransform();
856 parentRect.SetOffset(parentFrame->GetOffsetRelativeToWindow());
857 visibleRect = visibleRect.Constrain(parentRect);
858 parentUi = parentUi->GetParent();
859 }
860
861 double currentVisibleRatio =
862 std::clamp(CalculateCurrentVisibleRatio(visibleRect, frameRect), VISIBLE_RATIO_MIN, VISIBLE_RATIO_MAX);
863 if (!NearEqual(currentVisibleRatio, lastVisibleRatio_)) {
864 ProcessAllVisibleCallback(visibleAreaUserCallbacks_, currentVisibleRatio);
865 ProcessAllVisibleCallback(visibleAreaInnerCallbacks_, currentVisibleRatio);
866 lastVisibleRatio_ = currentVisibleRatio;
867 }
868 }
869
CalculateCurrentVisibleRatio(const RectF & visibleRect,const RectF & renderRect)870 double FrameNode::CalculateCurrentVisibleRatio(const RectF& visibleRect, const RectF& renderRect)
871 {
872 if (!visibleRect.IsValid() || !renderRect.IsValid()) {
873 return 0.0;
874 }
875 return visibleRect.Width() * visibleRect.Height() / (renderRect.Width() * renderRect.Height());
876 }
877
ProcessAllVisibleCallback(std::unordered_map<double,VisibleCallbackInfo> & visibleAreaCallbacks,double currentVisibleRatio)878 void FrameNode::ProcessAllVisibleCallback(
879 std::unordered_map<double, VisibleCallbackInfo>& visibleAreaCallbacks, double currentVisibleRatio)
880 {
881 bool isHandled = false;
882 for (auto& nodeCallbackInfo : visibleAreaCallbacks) {
883 auto callbackRatio = nodeCallbackInfo.first;
884 auto callbackIsVisible = nodeCallbackInfo.second.isCurrentVisible;
885 if (GreatNotEqual(currentVisibleRatio, callbackRatio) && !callbackIsVisible) {
886 OnVisibleAreaChangeCallback(nodeCallbackInfo.second, true, currentVisibleRatio, isHandled);
887 isHandled = true;
888 continue;
889 }
890
891 if (LessNotEqual(currentVisibleRatio, callbackRatio) && callbackIsVisible) {
892 OnVisibleAreaChangeCallback(nodeCallbackInfo.second, false, currentVisibleRatio, isHandled);
893 isHandled = true;
894 continue;
895 }
896
897 if (NearEqual(currentVisibleRatio, callbackRatio) && NearEqual(callbackRatio, VISIBLE_RATIO_MIN)) {
898 if (callbackIsVisible) {
899 OnVisibleAreaChangeCallback(nodeCallbackInfo.second, false, VISIBLE_RATIO_MIN, isHandled);
900 } else {
901 OnVisibleAreaChangeCallback(nodeCallbackInfo.second, true, VISIBLE_RATIO_MIN, isHandled);
902 }
903 isHandled = true;
904 } else if (NearEqual(currentVisibleRatio, callbackRatio) && NearEqual(callbackRatio, VISIBLE_RATIO_MAX)) {
905 if (!callbackIsVisible) {
906 OnVisibleAreaChangeCallback(nodeCallbackInfo.second, true, VISIBLE_RATIO_MAX, isHandled);
907 } else {
908 OnVisibleAreaChangeCallback(nodeCallbackInfo.second, false, VISIBLE_RATIO_MAX, isHandled);
909 }
910 isHandled = true;
911 }
912 }
913 }
914
OnVisibleAreaChangeCallback(VisibleCallbackInfo & callbackInfo,bool visibleType,double currentVisibleRatio,bool isHandled)915 void FrameNode::OnVisibleAreaChangeCallback(
916 VisibleCallbackInfo& callbackInfo, bool visibleType, double currentVisibleRatio, bool isHandled)
917 {
918 callbackInfo.isCurrentVisible = visibleType;
919 if (callbackInfo.callback && !isHandled) {
920 callbackInfo.callback(visibleType, currentVisibleRatio);
921 }
922 }
923
SetActive(bool active)924 void FrameNode::SetActive(bool active)
925 {
926 bool activeChanged = false;
927 if (active && !isActive_) {
928 pattern_->OnActive();
929 isActive_ = true;
930 activeChanged = true;
931 }
932 if (!active && isActive_) {
933 pattern_->OnInActive();
934 isActive_ = false;
935 activeChanged = true;
936 }
937 if (activeChanged) {
938 auto parent = GetAncestorNodeOfFrame();
939 if (parent) {
940 parent->MarkNeedSyncRenderTree();
941 }
942 }
943 if (GetTag() == V2::TAB_CONTENT_ITEM_ETS_TAG) {
944 SetJSViewActive(active);
945 }
946 }
947
SetGeometryNode(const RefPtr<GeometryNode> & node)948 void FrameNode::SetGeometryNode(const RefPtr<GeometryNode>& node)
949 {
950 geometryNode_ = node;
951 }
952
CreateLayoutTask(bool forceUseMainThread)953 std::optional<UITask> FrameNode::CreateLayoutTask(bool forceUseMainThread)
954 {
955 if (!isLayoutDirtyMarked_) {
956 return std::nullopt;
957 }
958 SetRootMeasureNode(true);
959 UpdateLayoutPropertyFlag();
960 {
961 ACE_SCOPED_TRACE("Measure");
962 Measure(GetLayoutConstraint());
963 }
964 {
965 ACE_SCOPED_TRACE("Layout");
966 Layout();
967 }
968 SetRootMeasureNode(false);
969 return std::nullopt;
970 }
971
CreateRenderTask(bool forceUseMainThread)972 std::optional<UITask> FrameNode::CreateRenderTask(bool forceUseMainThread)
973 {
974 if (!isRenderDirtyMarked_) {
975 return std::nullopt;
976 }
977 auto wrapper = CreatePaintWrapper();
978 CHECK_NULL_RETURN_NOLOG(wrapper, std::nullopt);
979 auto task = [weak = WeakClaim(this), wrapper, paintProperty = paintProperty_]() {
980 ACE_SCOPED_TRACE("FrameNode::RenderTask");
981 auto self = weak.Upgrade();
982 wrapper->FlushRender();
983 paintProperty->CleanDirty();
984
985 if (self->GetInspectorId()) {
986 auto pipeline = PipelineContext::GetCurrentContext();
987 CHECK_NULL_VOID(pipeline);
988 pipeline->SetNeedRenderNode(self);
989 }
990 };
991 if (forceUseMainThread || wrapper->CheckShouldRunOnMain()) {
992 return UITask(std::move(task), MAIN_TASK);
993 }
994 return UITask(std::move(task), wrapper->CanRunOnWhichThread());
995 }
996
GetLayoutConstraint() const997 LayoutConstraintF FrameNode::GetLayoutConstraint() const
998 {
999 if (geometryNode_->GetParentLayoutConstraint().has_value()) {
1000 return geometryNode_->GetParentLayoutConstraint().value();
1001 }
1002 LayoutConstraintF layoutConstraint;
1003 layoutConstraint.scaleProperty = ScaleProperty::CreateScaleProperty();
1004 auto rootWidth = PipelineContext::GetCurrentRootWidth();
1005 auto rootHeight = PipelineContext::GetCurrentRootHeight();
1006 layoutConstraint.percentReference.SetWidth(rootWidth);
1007 layoutConstraint.percentReference.SetHeight(rootHeight);
1008 layoutConstraint.maxSize.SetWidth(rootWidth);
1009 layoutConstraint.maxSize.SetHeight(rootHeight);
1010 return layoutConstraint;
1011 }
1012
GetParentGlobalOffset() const1013 OffsetF FrameNode::GetParentGlobalOffset() const
1014 {
1015 auto parent = GetAncestorNodeOfFrame();
1016 if (!parent) {
1017 return { 0.0f, 0.0f };
1018 }
1019 return parent->geometryNode_->GetParentGlobalOffset();
1020 }
1021
UpdateLayoutPropertyFlag()1022 void FrameNode::UpdateLayoutPropertyFlag()
1023 {
1024 auto selfFlag = layoutProperty_->GetPropertyChangeFlag();
1025 if (!CheckUpdateByChildRequest(selfFlag)) {
1026 return;
1027 }
1028 if (CheckForceParentMeasureFlag(selfFlag)) {
1029 return;
1030 }
1031 auto flag = PROPERTY_UPDATE_NORMAL;
1032 const auto& children = GetChildren();
1033 for (const auto& child : children) {
1034 child->UpdateLayoutPropertyFlag();
1035 child->AdjustParentLayoutFlag(flag);
1036 if (CheckForceParentMeasureFlag(selfFlag)) {
1037 break;
1038 }
1039 }
1040 if (CheckForceParentMeasureFlag(flag)) {
1041 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
1042 }
1043 }
1044
ForceUpdateLayoutPropertyFlag(PropertyChangeFlag propertyChangeFlag)1045 void FrameNode::ForceUpdateLayoutPropertyFlag(PropertyChangeFlag propertyChangeFlag)
1046 {
1047 layoutProperty_->UpdatePropertyChangeFlag(propertyChangeFlag);
1048 }
1049
AdjustParentLayoutFlag(PropertyChangeFlag & flag)1050 void FrameNode::AdjustParentLayoutFlag(PropertyChangeFlag& flag)
1051 {
1052 flag = flag | layoutProperty_->GetPropertyChangeFlag();
1053 }
1054
CreateLayoutWrapper(bool forceMeasure,bool forceLayout)1055 RefPtr<LayoutWrapperNode> FrameNode::CreateLayoutWrapper(bool forceMeasure, bool forceLayout)
1056 {
1057 return UpdateLayoutWrapper(nullptr, forceMeasure, forceLayout);
1058 }
1059
UpdateLayoutWrapper(RefPtr<LayoutWrapperNode> layoutWrapper,bool forceMeasure,bool forceLayout)1060 RefPtr<LayoutWrapperNode> FrameNode::UpdateLayoutWrapper(
1061 RefPtr<LayoutWrapperNode> layoutWrapper, bool forceMeasure, bool forceLayout)
1062 {
1063 CHECK_NULL_RETURN_NOLOG(layoutProperty_, nullptr);
1064 CHECK_NULL_RETURN_NOLOG(pattern_, nullptr);
1065 if (layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE) == VisibleType::GONE) {
1066 if (!layoutWrapper) {
1067 layoutWrapper =
1068 MakeRefPtr<LayoutWrapperNode>(WeakClaim(this), MakeRefPtr<GeometryNode>(), layoutProperty_->Clone());
1069 } else {
1070 layoutWrapper->Update(WeakClaim(this), MakeRefPtr<GeometryNode>(), layoutProperty_->Clone());
1071 }
1072 layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(nullptr, true, true));
1073 isLayoutDirtyMarked_ = false;
1074 return layoutWrapper;
1075 }
1076
1077 pattern_->BeforeCreateLayoutWrapper();
1078 if (forceMeasure) {
1079 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
1080 }
1081 if (forceLayout) {
1082 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_LAYOUT);
1083 }
1084 auto flag = layoutProperty_->GetPropertyChangeFlag();
1085 // It is necessary to copy the layoutProperty property to prevent the layoutProperty property from being
1086 // modified during the layout process, resulting in the problem of judging whether the front-end setting value
1087 // changes the next time js is executed.
1088 if (!layoutWrapper) {
1089 layoutWrapper =
1090 MakeRefPtr<LayoutWrapperNode>(WeakClaim(this), geometryNode_->Clone(), layoutProperty_->Clone());
1091 } else {
1092 layoutWrapper->Update(WeakClaim(this), geometryNode_->Clone(), layoutProperty_->Clone());
1093 }
1094 LOGD("%{public}s create layout wrapper: %{public}x, %{public}d, %{public}d", GetTag().c_str(), flag, forceMeasure,
1095 forceLayout);
1096 do {
1097 if (CheckNeedMeasure(flag) || forceMeasure) {
1098 layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm()));
1099 bool forceChildMeasure = CheckMeasureFlag(flag) || CheckMeasureSelfAndChildFlag(flag) || forceMeasure;
1100 UpdateChildrenLayoutWrapper(layoutWrapper, forceChildMeasure, false);
1101 break;
1102 }
1103 if (CheckNeedLayout(flag) || forceLayout) {
1104 layoutWrapper->SetLayoutAlgorithm(
1105 MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm(), true, false));
1106 UpdateChildrenLayoutWrapper(layoutWrapper, false, false);
1107 break;
1108 }
1109 layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(nullptr, true, true));
1110 } while (false);
1111 // check position flag.
1112 layoutWrapper->SetOutOfLayout(renderContext_->HasPosition());
1113 layoutWrapper->SetActive(isActive_);
1114 layoutWrapper->SetIsOverlayNode(layoutProperty_->IsOverlayNode());
1115 isLayoutDirtyMarked_ = false;
1116 return layoutWrapper;
1117 }
1118
UpdateChildrenLayoutWrapper(const RefPtr<LayoutWrapperNode> & self,bool forceMeasure,bool forceLayout)1119 void FrameNode::UpdateChildrenLayoutWrapper(const RefPtr<LayoutWrapperNode>& self, bool forceMeasure, bool forceLayout)
1120 {
1121 const auto& children = GetChildren();
1122 for (const auto& child : children) {
1123 child->AdjustLayoutWrapperTree(self, forceMeasure, forceLayout);
1124 }
1125 }
1126
AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode> & parent,bool forceMeasure,bool forceLayout)1127 void FrameNode::AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode>& parent, bool forceMeasure, bool forceLayout)
1128 {
1129 ACE_DCHECK(parent);
1130 CHECK_NULL_VOID(layoutProperty_);
1131 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
1132 if (geometryTransition != nullptr && geometryTransition->IsNodeOutAndActive(WeakClaim(this))) {
1133 return;
1134 }
1135 auto layoutWrapper = CreateLayoutWrapper(forceMeasure, forceLayout);
1136 parent->AppendChild(layoutWrapper, layoutProperty_->IsOverlayNode());
1137 }
1138
CreatePaintWrapper()1139 RefPtr<PaintWrapper> FrameNode::CreatePaintWrapper()
1140 {
1141 pattern_->BeforeCreatePaintWrapper();
1142 isRenderDirtyMarked_ = false;
1143 auto paintMethod = pattern_->CreateNodePaintMethod();
1144 // It is necessary to copy the layoutProperty property to prevent the paintProperty_ property from being
1145 // modified during the paint process, resulting in the problem of judging whether the front-end setting value
1146 // changes the next time js is executed.
1147 if (paintMethod) {
1148 auto paintWrapper = MakeRefPtr<PaintWrapper>(renderContext_, geometryNode_->Clone(), paintProperty_->Clone());
1149 paintWrapper->SetNodePaintMethod(paintMethod);
1150 return paintWrapper;
1151 }
1152 if (renderContext_->GetAccessibilityFocus().value_or(false)) {
1153 auto paintWrapper = MakeRefPtr<PaintWrapper>(renderContext_, geometryNode_->Clone(), paintProperty_->Clone());
1154 paintWrapper->SetNodePaintMethod(MakeRefPtr<NodePaintMethod>());
1155 return paintWrapper;
1156 }
1157 return nullptr;
1158 }
1159
PostTask(std::function<void ()> && task,TaskExecutor::TaskType taskType)1160 void FrameNode::PostTask(std::function<void()>&& task, TaskExecutor::TaskType taskType)
1161 {
1162 auto context = GetContext();
1163 CHECK_NULL_VOID(context);
1164 context->PostAsyncEvent(std::move(task), taskType);
1165 }
1166
UpdateLayoutConstraint(const MeasureProperty & calcLayoutConstraint)1167 void FrameNode::UpdateLayoutConstraint(const MeasureProperty& calcLayoutConstraint)
1168 {
1169 layoutProperty_->UpdateCalcLayoutProperty(calcLayoutConstraint);
1170 }
1171
RebuildRenderContextTree()1172 void FrameNode::RebuildRenderContextTree()
1173 {
1174 if (!needSyncRenderTree_) {
1175 return;
1176 }
1177 frameChildren_.clear();
1178 std::list<RefPtr<FrameNode>> children;
1179 // generate full children list, including disappear children.
1180 GenerateOneDepthVisibleFrameWithTransition(children);
1181 if (overlayNode_) {
1182 children.push_back(overlayNode_);
1183 }
1184 for (const auto& child : children) {
1185 frameChildren_.emplace(child);
1186 }
1187 renderContext_->RebuildFrame(this, children);
1188 pattern_->OnRebuildFrame();
1189 needSyncRenderTree_ = false;
1190 }
1191
MarkModifyDone()1192 void FrameNode::MarkModifyDone()
1193 {
1194 pattern_->OnModifyDone();
1195 // restore info will overwrite the first setted attribute
1196 if (!isRestoreInfoUsed_) {
1197 isRestoreInfoUsed_ = true;
1198 auto pipeline = PipelineContext::GetCurrentContext();
1199 int32_t restoreId = GetRestoreId();
1200 if (pipeline && restoreId >= 0) {
1201 // store distribute node
1202 pipeline->StoreNode(restoreId, AceType::WeakClaim(this));
1203 // restore distribute node info
1204 std::string restoreInfo;
1205 if (pipeline->GetRestoreInfo(restoreId, restoreInfo)) {
1206 pattern_->OnRestoreInfo(restoreInfo);
1207 }
1208 }
1209 }
1210 eventHub_->MarkModifyDone();
1211 if (IsResponseRegion() || HasPositionProp()) {
1212 auto parent = GetParent();
1213 while (parent) {
1214 auto frameNode = AceType::DynamicCast<FrameNode>(parent);
1215 if (frameNode) {
1216 frameNode->MarkResponseRegion(true);
1217 }
1218 parent = parent->GetParent();
1219 }
1220 }
1221 renderContext_->OnModifyDone();
1222 }
1223
OnMountToParentDone()1224 void FrameNode::OnMountToParentDone()
1225 {
1226 pattern_->OnMountToParentDone();
1227 }
1228
FlushUpdateAndMarkDirty()1229 void FrameNode::FlushUpdateAndMarkDirty()
1230 {
1231 MarkDirtyNode();
1232 }
1233
MarkDirtyNode(PropertyChangeFlag extraFlag)1234 void FrameNode::MarkDirtyNode(PropertyChangeFlag extraFlag)
1235 {
1236 MarkDirtyNode(IsMeasureBoundary(), IsRenderBoundary(), extraFlag);
1237 }
1238
GetAncestorNodeOfFrame() const1239 RefPtr<FrameNode> FrameNode::GetAncestorNodeOfFrame() const
1240 {
1241 auto parent = GetParent();
1242 while (parent) {
1243 if (InstanceOf<FrameNode>(parent)) {
1244 return DynamicCast<FrameNode>(parent);
1245 }
1246 parent = parent->GetParent();
1247 }
1248 return nullptr;
1249 }
1250
MarkNeedRenderOnly()1251 void FrameNode::MarkNeedRenderOnly()
1252 {
1253 MarkNeedRender(IsRenderBoundary());
1254 }
1255
MarkNeedRender(bool isRenderBoundary)1256 void FrameNode::MarkNeedRender(bool isRenderBoundary)
1257 {
1258 auto context = GetContext();
1259 CHECK_NULL_VOID(context);
1260 // If it has dirtyLayoutBox, need to mark dirty after layout done.
1261 paintProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_RENDER);
1262 if (isRenderDirtyMarked_ || isLayoutDirtyMarked_) {
1263 LOGD("this node has already mark dirty, %{public}s, %{public}d, %{public}d", GetTag().c_str(),
1264 isRenderDirtyMarked_, isLayoutDirtyMarked_);
1265 return;
1266 }
1267 isRenderDirtyMarked_ = true;
1268 if (isRenderBoundary) {
1269 context->AddDirtyRenderNode(Claim(this));
1270 return;
1271 }
1272 auto parent = GetAncestorNodeOfFrame();
1273 if (parent) {
1274 parent->MarkDirtyNode(PROPERTY_UPDATE_RENDER_BY_CHILD_REQUEST);
1275 }
1276 }
1277
MarkDirtyNode(bool isMeasureBoundary,bool isRenderBoundary,PropertyChangeFlag extraFlag)1278 void FrameNode::MarkDirtyNode(bool isMeasureBoundary, bool isRenderBoundary, PropertyChangeFlag extraFlag)
1279 {
1280 if (CheckNeedRender(extraFlag)) {
1281 paintProperty_->UpdatePropertyChangeFlag(extraFlag);
1282 }
1283 layoutProperty_->UpdatePropertyChangeFlag(extraFlag);
1284 paintProperty_->UpdatePropertyChangeFlag(extraFlag);
1285 auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
1286 auto paintFlag = paintProperty_->GetPropertyChangeFlag();
1287 if (CheckNoChanged(layoutFlag | paintFlag)) {
1288 LOGD("MarkDirtyNode: flag not changed, node tag: %{public}s", GetTag().c_str());
1289 return;
1290 }
1291 auto context = GetContext();
1292 CHECK_NULL_VOID(context);
1293
1294 if (CheckNeedRequestMeasureAndLayout(layoutFlag)) {
1295 if (!isMeasureBoundary && IsNeedRequestParentMeasure()) {
1296 auto parent = GetAncestorNodeOfFrame();
1297 if (parent) {
1298 parent->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
1299 return;
1300 }
1301 }
1302 if (isLayoutDirtyMarked_) {
1303 LOGD("MarkDirtyNode: isLayoutDirtyMarked is true");
1304 return;
1305 }
1306 isLayoutDirtyMarked_ = true;
1307 context->AddDirtyLayoutNode(Claim(this));
1308 return;
1309 }
1310 layoutProperty_->CleanDirty();
1311 MarkNeedRender(isRenderBoundary);
1312 }
1313
IsNeedRequestParentMeasure() const1314 bool FrameNode::IsNeedRequestParentMeasure() const
1315 {
1316 auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
1317 if (layoutFlag == PROPERTY_UPDATE_BY_CHILD_REQUEST) {
1318 const auto& calcLayoutConstraint = layoutProperty_->GetCalcLayoutConstraint();
1319 if (calcLayoutConstraint && calcLayoutConstraint->selfIdealSize &&
1320 calcLayoutConstraint->selfIdealSize->IsValid()) {
1321 LOGD("make self measure boundary");
1322 return false;
1323 }
1324 }
1325 return CheckNeedRequestParentMeasure(layoutFlag);
1326 }
1327
OnGenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>> & visibleList)1328 void FrameNode::OnGenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>>& visibleList)
1329 {
1330 if (isActive_ && IsVisible()) {
1331 visibleList.emplace_back(Claim(this));
1332 }
1333 }
1334
OnGenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>> & allList)1335 void FrameNode::OnGenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>>& allList)
1336 {
1337 allList.emplace_back(Claim(this));
1338 }
1339
OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>> & visibleList)1340 void FrameNode::OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>>& visibleList)
1341 {
1342 auto context = GetRenderContext();
1343 CHECK_NULL_VOID(context);
1344 // skip if 1.not active or 2.not visible and has no transition out animation.
1345 if (!isActive_ || (!IsVisible() && !context->HasTransitionOutAnimation())) {
1346 return;
1347 }
1348 visibleList.emplace_back(Claim(this));
1349 }
1350
IsMeasureBoundary()1351 bool FrameNode::IsMeasureBoundary()
1352 {
1353 return isMeasureBoundary_ || pattern_->IsMeasureBoundary();
1354 }
1355
IsRenderBoundary()1356 bool FrameNode::IsRenderBoundary()
1357 {
1358 return pattern_->IsRenderBoundary();
1359 }
1360
GetPattern() const1361 const RefPtr<Pattern>& FrameNode::GetPattern() const
1362 {
1363 return pattern_;
1364 }
1365
IsAtomicNode() const1366 bool FrameNode::IsAtomicNode() const
1367 {
1368 return pattern_->IsAtomicNode();
1369 }
1370
GetHitTestMode() const1371 HitTestMode FrameNode::GetHitTestMode() const
1372 {
1373 auto gestureHub = eventHub_->GetGestureEventHub();
1374 return gestureHub ? gestureHub->GetHitTestMode() : HitTestMode::HTMDEFAULT;
1375 }
1376
SetHitTestMode(HitTestMode mode)1377 void FrameNode::SetHitTestMode(HitTestMode mode)
1378 {
1379 auto gestureHub = eventHub_->GetOrCreateGestureEventHub();
1380 CHECK_NULL_VOID(gestureHub);
1381 gestureHub->SetHitTestMode(mode);
1382 }
1383
GetTouchable() const1384 bool FrameNode::GetTouchable() const
1385 {
1386 auto gestureHub = eventHub_->GetGestureEventHub();
1387 return gestureHub ? gestureHub->GetTouchable() : true;
1388 }
1389
IsResponseRegion() const1390 bool FrameNode::IsResponseRegion() const
1391 {
1392 auto renderContext = GetRenderContext();
1393 CHECK_NULL_RETURN(renderContext, false);
1394 auto clip = renderContext->GetClipEdge().value_or(false);
1395 if (clip) {
1396 return false;
1397 }
1398 auto gestureHub = eventHub_->GetGestureEventHub();
1399 return gestureHub ? gestureHub->IsResponseRegion() : false;
1400 }
1401
MarkResponseRegion(bool isResponseRegion)1402 void FrameNode::MarkResponseRegion(bool isResponseRegion)
1403 {
1404 auto gestureHub = eventHub_->GetOrCreateGestureEventHub();
1405 if (gestureHub) {
1406 gestureHub->MarkResponseRegion(isResponseRegion);
1407 }
1408 }
1409
GetPaintRectWithTransform() const1410 RectF FrameNode::GetPaintRectWithTransform() const
1411 {
1412 return renderContext_->GetPaintRectWithTransform();
1413 }
1414
GetTransformScale() const1415 VectorF FrameNode::GetTransformScale() const
1416 {
1417 return renderContext_->GetTransformScaleValue({ 1.0f, 1.0f });
1418 }
1419
IsOutOfTouchTestRegion(const PointF & parentRevertPoint,int32_t sourceType)1420 bool FrameNode::IsOutOfTouchTestRegion(const PointF& parentRevertPoint, int32_t sourceType)
1421 {
1422 bool isInChildRegion = false;
1423 auto paintRect = renderContext_->GetPaintRectWithoutTransform();
1424 auto responseRegionList = GetResponseRegionList(paintRect, sourceType);
1425 auto renderContext = GetRenderContext();
1426 CHECK_NULL_RETURN(renderContext, false);
1427
1428 auto revertPoint = parentRevertPoint;
1429 renderContext->GetPointWithRevert(revertPoint);
1430 auto subRevertPoint = revertPoint - paintRect.GetOffset();
1431 auto clip = renderContext->GetClipEdge().value_or(false);
1432 if (!InResponseRegionList(revertPoint, responseRegionList) || !GetTouchable()) {
1433 if (clip) {
1434 if (SystemProperties::GetDebugEnabled()) {
1435 LOGI("TouchTest: frameNode use clip, point is out of region in %{public}s", GetTag().c_str());
1436 }
1437 return true;
1438 }
1439 for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
1440 const auto& child = iter->Upgrade();
1441 if (child && !child->IsOutOfTouchTestRegion(subRevertPoint, sourceType)) {
1442 if (SystemProperties::GetDebugEnabled()) {
1443 LOGI("TouchTest: point is out of region in %{public}s, but is in child region", GetTag().c_str());
1444 }
1445 isInChildRegion = true;
1446 break;
1447 }
1448 }
1449 if (!isInChildRegion) {
1450 if (SystemProperties::GetDebugEnabled()) {
1451 LOGI("TouchTest: point is out of region in %{public}s", GetTag().c_str());
1452 }
1453 return true;
1454 }
1455 }
1456 return false;
1457 }
1458
TouchTest(const PointF & globalPoint,const PointF & parentLocalPoint,const PointF & parentRevertPoint,const TouchRestrict & touchRestrict,TouchTestResult & result,int32_t touchId)1459 HitTestResult FrameNode::TouchTest(const PointF& globalPoint, const PointF& parentLocalPoint,
1460 const PointF& parentRevertPoint, const TouchRestrict& touchRestrict, TouchTestResult& result, int32_t touchId)
1461 {
1462 if (!isActive_ || !eventHub_->IsEnabled() || bypass_) {
1463 if (SystemProperties::GetDebugEnabled()) {
1464 LOGI("%{public}s is inActive, need't do touch test", GetTag().c_str());
1465 }
1466 return HitTestResult::OUT_OF_REGION;
1467 }
1468 auto& translateIds = NGGestureRecognizer::GetGlobalTransIds();
1469 auto& translateCfg = NGGestureRecognizer::GetGlobalTransCfg();
1470 auto paintRect = renderContext_->GetPaintRectWithTransform();
1471 auto origRect = renderContext_->GetPaintRectWithoutTransform();
1472 auto param = renderContext_->GetTrans();
1473 if (param.empty()) {
1474 translateCfg[GetId()] = { .id = GetId() };
1475 } else {
1476 translateCfg[GetId()] = { param[0], param[1], param[2], param[3], param[4], param[5], param[6], param[7],
1477 param[8], GetId() };
1478 }
1479 auto parent = GetAncestorNodeOfFrame();
1480 if (parent) {
1481 AncestorNodeInfo ancestorNodeInfo { parent->GetId() };
1482 translateIds[GetId()] = ancestorNodeInfo;
1483 }
1484
1485 auto responseRegionList = GetResponseRegionList(origRect, static_cast<int32_t>(touchRestrict.sourceType));
1486 if (SystemProperties::GetDebugEnabled()) {
1487 LOGI("TouchTest: point is %{public}s in %{public}s, depth: %{public}d", parentRevertPoint.ToString().c_str(),
1488 GetTag().c_str(), GetDepth());
1489 for (const auto& rect : responseRegionList) {
1490 LOGI("TouchTest: responseRegionList is %{public}s, point is %{public}s", rect.ToString().c_str(),
1491 parentRevertPoint.ToString().c_str());
1492 }
1493 }
1494 {
1495 ACE_DEBUG_SCOPED_TRACE("FrameNode::IsOutOfTouchTestRegion");
1496 if (IsOutOfTouchTestRegion(parentRevertPoint, static_cast<int32_t>(touchRestrict.sourceType))) {
1497 return HitTestResult::OUT_OF_REGION;
1498 }
1499 }
1500
1501 HitTestResult testResult = HitTestResult::OUT_OF_REGION;
1502 bool preventBubbling = false;
1503 // Child nodes are repackaged into gesture groups (parallel gesture groups, exclusive gesture groups, etc.)
1504 // based on the gesture attributes set by the current parent node (high and low priority, parallel gestures,
1505 // etc.), the newComingTargets is the template object to collect child nodes gesture and used by gestureHub to
1506 // pack gesture group.
1507 TouchTestResult newComingTargets;
1508 auto tmp = parentLocalPoint - paintRect.GetOffset();
1509 auto preLocation = tmp;
1510 renderContext_->GetPointWithTransform(tmp);
1511 const auto localPoint = tmp;
1512 auto localTransformOffset = preLocation - localPoint;
1513
1514 auto revertPoint = parentRevertPoint;
1515 renderContext_->GetPointWithRevert(revertPoint);
1516 auto subRevertPoint = revertPoint - origRect.GetOffset();
1517 bool consumed = false;
1518 for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
1519 if (GetHitTestMode() == HitTestMode::HTMBLOCK) {
1520 break;
1521 }
1522
1523 const auto& child = iter->Upgrade();
1524 if (!child) {
1525 continue;
1526 }
1527 auto childHitResult = child->TouchTest(globalPoint, localPoint, subRevertPoint, touchRestrict,
1528 newComingTargets, touchId);
1529 if (childHitResult == HitTestResult::STOP_BUBBLING) {
1530 preventBubbling = true;
1531 consumed = true;
1532 if ((child->GetHitTestMode() == HitTestMode::HTMBLOCK) ||
1533 (child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
1534 (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ||
1535 ((child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT) && IsExclusiveEventForChild())) {
1536 break;
1537 }
1538 }
1539
1540 // In normal process, the node block the brother node.
1541 if (childHitResult == HitTestResult::BUBBLING &&
1542 ((child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
1543 (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ||
1544 ((child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT) && IsExclusiveEventForChild()))) {
1545 consumed = true;
1546 break;
1547 }
1548 }
1549
1550 // first update HitTestResult by children status.
1551 if (consumed) {
1552 testResult = preventBubbling ? HitTestResult::STOP_BUBBLING : HitTestResult::BUBBLING;
1553 consumed = false;
1554 } else if (GetHitTestMode() == HitTestMode::HTMBLOCK) {
1555 testResult = HitTestResult::STOP_BUBBLING;
1556 }
1557
1558 if (!preventBubbling && (GetHitTestMode() != HitTestMode::HTMNONE) &&
1559 (InResponseRegionList(revertPoint, responseRegionList))) {
1560 pattern_->OnTouchTestHit(touchRestrict.hitTestType);
1561 consumed = true;
1562 if (touchRestrict.hitTestType == SourceType::TOUCH) {
1563 auto gestureHub = eventHub_->GetGestureEventHub();
1564 if (gestureHub) {
1565 TouchTestResult finalResult;
1566 const auto coordinateOffset = globalPoint - localPoint - localTransformOffset;
1567 preventBubbling = gestureHub->ProcessTouchTestHit(
1568 coordinateOffset, touchRestrict, newComingTargets, finalResult, touchId, localPoint);
1569 newComingTargets.swap(finalResult);
1570 }
1571 } else if (touchRestrict.hitTestType == SourceType::MOUSE) {
1572 auto mouseHub = eventHub_->GetInputEventHub();
1573 if (mouseHub) {
1574 const auto coordinateOffset = globalPoint - localPoint;
1575 preventBubbling = mouseHub->ProcessMouseTestHit(coordinateOffset, newComingTargets);
1576 }
1577 }
1578 }
1579
1580 result.splice(result.end(), std::move(newComingTargets));
1581 if (touchRestrict.hitTestType == SourceType::TOUCH) {
1582 // combine into exclusive recognizer group.
1583 auto gestureHub = eventHub_->GetGestureEventHub();
1584 if (gestureHub) {
1585 gestureHub->CombineIntoExclusiveRecognizer(globalPoint, localPoint, result, touchId);
1586 }
1587 }
1588
1589 // consumed by children and return result.
1590 if (!consumed) {
1591 return testResult;
1592 }
1593
1594 if (testResult == HitTestResult::OUT_OF_REGION) {
1595 // consume only by self.
1596 if (preventBubbling) {
1597 return HitTestResult::STOP_BUBBLING;
1598 }
1599 return (GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ? HitTestResult::SELF_TRANSPARENT
1600 : HitTestResult::BUBBLING;
1601 }
1602 // consume by self and children.
1603 return testResult;
1604 }
1605
GetResponseRegionList(const RectF & rect,int32_t sourceType)1606 std::vector<RectF> FrameNode::GetResponseRegionList(const RectF& rect, int32_t sourceType)
1607 {
1608 std::vector<RectF> responseRegionList;
1609 auto gestureHub = eventHub_->GetGestureEventHub();
1610 if (!gestureHub) {
1611 responseRegionList.emplace_back(rect);
1612 return responseRegionList;
1613 }
1614 auto scaleProperty = ScaleProperty::CreateScaleProperty();
1615 bool isMouseEvent = (static_cast<SourceType>(sourceType) == SourceType::MOUSE);
1616 if (isMouseEvent) {
1617 if (gestureHub->GetResponseRegion().empty() && (gestureHub->GetMouseResponseRegion().empty())) {
1618 responseRegionList.emplace_back(rect);
1619 return responseRegionList;
1620 }
1621 } else {
1622 if (gestureHub->GetResponseRegion().empty()) {
1623 responseRegionList.emplace_back(rect);
1624 return responseRegionList;
1625 }
1626 }
1627
1628 if (isMouseEvent && (!gestureHub->GetMouseResponseRegion().empty())) {
1629 for (const auto& region : gestureHub->GetMouseResponseRegion()) {
1630 auto x = ConvertToPx(region.GetOffset().GetX(), scaleProperty, rect.Width());
1631 auto y = ConvertToPx(region.GetOffset().GetY(), scaleProperty, rect.Height());
1632 auto width = ConvertToPx(region.GetWidth(), scaleProperty, rect.Width());
1633 auto height = ConvertToPx(region.GetHeight(), scaleProperty, rect.Height());
1634 RectF mouseRegion(rect.GetOffset().GetX() + x.value(), rect.GetOffset().GetY() + y.value(), width.value(),
1635 height.value());
1636 responseRegionList.emplace_back(mouseRegion);
1637 }
1638 return responseRegionList;
1639 }
1640 for (const auto& region : gestureHub->GetResponseRegion()) {
1641 auto x = ConvertToPx(region.GetOffset().GetX(), scaleProperty, rect.Width());
1642 auto y = ConvertToPx(region.GetOffset().GetY(), scaleProperty, rect.Height());
1643 auto width = ConvertToPx(region.GetWidth(), scaleProperty, rect.Width());
1644 auto height = ConvertToPx(region.GetHeight(), scaleProperty, rect.Height());
1645 RectF responseRegion(
1646 rect.GetOffset().GetX() + x.value(), rect.GetOffset().GetY() + y.value(), width.value(), height.value());
1647 responseRegionList.emplace_back(responseRegion);
1648 }
1649 return responseRegionList;
1650 }
1651
InResponseRegionList(const PointF & parentLocalPoint,const std::vector<RectF> & responseRegionList) const1652 bool FrameNode::InResponseRegionList(const PointF& parentLocalPoint, const std::vector<RectF>& responseRegionList) const
1653 {
1654 for (const auto& rect : responseRegionList) {
1655 if (rect.IsInRegion(parentLocalPoint)) {
1656 return true;
1657 }
1658 }
1659 return false;
1660 }
1661
MouseTest(const PointF & globalPoint,const PointF & parentLocalPoint,MouseTestResult & onMouseResult,MouseTestResult & onHoverResult,RefPtr<FrameNode> & hoverNode)1662 HitTestResult FrameNode::MouseTest(const PointF& globalPoint, const PointF& parentLocalPoint,
1663 MouseTestResult& onMouseResult, MouseTestResult& onHoverResult, RefPtr<FrameNode>& hoverNode)
1664 {
1665 // unuseable function. do nothing.
1666 return HitTestResult::BUBBLING;
1667 }
1668
AxisTest(const PointF & globalPoint,const PointF & parentLocalPoint,AxisTestResult & onAxisResult)1669 HitTestResult FrameNode::AxisTest(
1670 const PointF& globalPoint, const PointF& parentLocalPoint, AxisTestResult& onAxisResult)
1671 {
1672 const auto& rect = renderContext_->GetPaintRectWithTransform();
1673 LOGD("AxisTest: type is %{public}s, the region is %{public}lf, %{public}lf, %{public}lf, %{public}lf",
1674 GetTag().c_str(), rect.Left(), rect.Top(), rect.Width(), rect.Height());
1675 // TODO: disableTouchEvent || disabled_ need handle
1676
1677 // TODO: Region need change to RectList
1678 if (!rect.IsInRegion(parentLocalPoint)) {
1679 return HitTestResult::OUT_OF_REGION;
1680 }
1681
1682 bool preventBubbling = false;
1683
1684 const auto localPoint = parentLocalPoint - rect.GetOffset();
1685 const auto& children = GetChildren();
1686 for (auto iter = children.rbegin(); iter != children.rend(); ++iter) {
1687 auto& child = *iter;
1688 auto childHitResult = child->AxisTest(globalPoint, localPoint, onAxisResult);
1689 if (childHitResult == HitTestResult::STOP_BUBBLING) {
1690 preventBubbling = true;
1691 }
1692 // In normal process, the node block the brother node.
1693 if (childHitResult == HitTestResult::BUBBLING) {
1694 // TODO: add hit test mode judge.
1695 break;
1696 }
1697 }
1698
1699 AxisTestResult axisResult;
1700 bool isPrevent = false;
1701 auto inputHub = eventHub_->GetInputEventHub();
1702 if (inputHub) {
1703 const auto coordinateOffset = globalPoint - localPoint;
1704 isPrevent = inputHub->ProcessAxisTestHit(coordinateOffset, axisResult);
1705 }
1706
1707 if (!preventBubbling) {
1708 preventBubbling = isPrevent;
1709 onAxisResult.splice(onAxisResult.end(), std::move(axisResult));
1710 }
1711 if (preventBubbling) {
1712 return HitTestResult::STOP_BUBBLING;
1713 }
1714 return HitTestResult::BUBBLING;
1715 }
1716
AnimateHoverEffect(bool isHovered) const1717 void FrameNode::AnimateHoverEffect(bool isHovered) const
1718 {
1719 auto renderContext = GetRenderContext();
1720 if (!renderContext) {
1721 return;
1722 }
1723 HoverEffectType animationType = HoverEffectType::UNKNOWN;
1724 auto inputEventHub = eventHub_->GetInputEventHub();
1725 if (inputEventHub) {
1726 animationType = inputEventHub->GetHoverEffect();
1727 if (animationType == HoverEffectType::UNKNOWN || animationType == HoverEffectType::AUTO) {
1728 animationType = inputEventHub->GetHoverEffectAuto();
1729 }
1730 }
1731 if (animationType == HoverEffectType::SCALE) {
1732 renderContext->AnimateHoverEffectScale(isHovered);
1733 } else if (animationType == HoverEffectType::BOARD) {
1734 renderContext->AnimateHoverEffectBoard(isHovered);
1735 }
1736 }
1737
GetOrCreateFocusHub() const1738 RefPtr<FocusHub> FrameNode::GetOrCreateFocusHub() const
1739 {
1740 if (!pattern_) {
1741 return eventHub_->GetOrCreateFocusHub();
1742 }
1743 auto focusPattern = pattern_->GetFocusPattern();
1744 return eventHub_->GetOrCreateFocusHub(focusPattern.GetFocusType(), focusPattern.GetFocusable(),
1745 focusPattern.GetStyleType(), focusPattern.GetFocusPaintParams());
1746 }
1747
OnWindowShow()1748 void FrameNode::OnWindowShow()
1749 {
1750 pattern_->OnWindowShow();
1751 }
1752
OnWindowHide()1753 void FrameNode::OnWindowHide()
1754 {
1755 pattern_->OnWindowHide();
1756 }
1757
OnWindowFocused()1758 void FrameNode::OnWindowFocused()
1759 {
1760 pattern_->OnWindowFocused();
1761 }
1762
OnWindowUnfocused()1763 void FrameNode::OnWindowUnfocused()
1764 {
1765 pattern_->OnWindowUnfocused();
1766 }
1767
ContextPositionConvertToPX(const RefPtr<RenderContext> & context,const SizeF & percentReference) const1768 std::pair<float, float> FrameNode::ContextPositionConvertToPX(
1769 const RefPtr<RenderContext>& context, const SizeF& percentReference) const
1770 {
1771 std::pair<float, float> position;
1772 CHECK_NULL_RETURN_NOLOG(context, position);
1773 auto scaleProperty = ScaleProperty::CreateScaleProperty();
1774 position.first =
1775 ConvertToPx(context->GetPositionProperty()->GetPosition()->GetX(), scaleProperty, percentReference.Width())
1776 .value_or(0.0);
1777 position.second =
1778 ConvertToPx(context->GetPositionProperty()->GetPosition()->GetY(), scaleProperty, percentReference.Height())
1779 .value_or(0.0);
1780 return position;
1781 }
1782
OnWindowSizeChanged(int32_t width,int32_t height,WindowSizeChangeReason type)1783 void FrameNode::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
1784 {
1785 pattern_->OnWindowSizeChanged(width, height, type);
1786 }
1787
GetOffsetRelativeToWindow() const1788 OffsetF FrameNode::GetOffsetRelativeToWindow() const
1789 {
1790 auto offset = geometryNode_->GetFrameOffset();
1791 auto parent = GetAncestorNodeOfFrame();
1792 if (renderContext_ && renderContext_->GetPositionProperty()) {
1793 if (renderContext_->GetPositionProperty()->HasPosition()) {
1794 auto renderPosition =
1795 ContextPositionConvertToPX(renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
1796 offset.SetX(static_cast<float>(renderPosition.first));
1797 offset.SetY(static_cast<float>(renderPosition.second));
1798 }
1799 }
1800 while (parent) {
1801 auto parentRenderContext = parent->GetRenderContext();
1802 if (parentRenderContext && parentRenderContext->GetPositionProperty()) {
1803 if (parentRenderContext->GetPositionProperty()->HasPosition()) {
1804 auto parentLayoutProperty = parent->GetLayoutProperty();
1805 CHECK_NULL_RETURN_NOLOG(parentLayoutProperty, offset);
1806 auto parentRenderContextPosition = ContextPositionConvertToPX(
1807 parentRenderContext, parentLayoutProperty->GetLayoutConstraint()->percentReference);
1808 offset.AddX(static_cast<float>(parentRenderContextPosition.first));
1809 offset.AddY(static_cast<float>(parentRenderContextPosition.second));
1810 parent = parent->GetAncestorNodeOfFrame();
1811 continue;
1812 }
1813 }
1814
1815 offset += parent->geometryNode_->GetFrameOffset();
1816 parent = parent->GetAncestorNodeOfFrame();
1817 }
1818
1819 return offset;
1820 }
1821
GetTransformRectRelativeToWindow() const1822 RectF FrameNode::GetTransformRectRelativeToWindow() const
1823 {
1824 auto context = GetRenderContext();
1825 CHECK_NULL_RETURN(context, RectF());
1826 RectF rect = context->GetPaintRectWithTransform();
1827 auto offset = rect.GetOffset();
1828 auto parent = GetAncestorNodeOfFrame();
1829 while (parent) {
1830 auto parentRenderContext = parent->GetRenderContext();
1831 CHECK_NULL_RETURN(parentRenderContext, rect);
1832 auto parentScale = parentRenderContext->GetTransformScale();
1833 if (parentScale) {
1834 auto oldSize = rect.GetSize();
1835 auto newSize = SizeF(oldSize.Width() * parentScale.value().x, oldSize.Height() * parentScale.value().y);
1836 rect.SetSize(newSize);
1837
1838 offset = OffsetF(offset.GetX() * parentScale.value().x, offset.GetY() * parentScale.value().y);
1839 }
1840
1841 offset += parentRenderContext->GetPaintRectWithTransform().GetOffset();
1842
1843 parent = parent->GetAncestorNodeOfFrame();
1844 }
1845 rect.SetOffset(offset);
1846 return rect;
1847 }
1848
GetTransformRelativeOffset() const1849 OffsetF FrameNode::GetTransformRelativeOffset() const
1850 {
1851 auto context = GetRenderContext();
1852 CHECK_NULL_RETURN(context, OffsetF());
1853 auto offset = context->GetPaintRectWithTransform().GetOffset();
1854 auto parent = GetAncestorNodeOfFrame();
1855
1856 while (parent) {
1857 auto parentRenderContext = parent->GetRenderContext();
1858 offset += parentRenderContext->GetPaintRectWithTransform().GetOffset();
1859 parent = parent->GetAncestorNodeOfFrame();
1860 }
1861
1862 return offset;
1863 }
1864
GetPaintRectOffset(bool excludeSelf) const1865 OffsetF FrameNode::GetPaintRectOffset(bool excludeSelf) const
1866 {
1867 auto context = GetRenderContext();
1868 CHECK_NULL_RETURN(context, OffsetF());
1869 OffsetF offset = excludeSelf ? OffsetF() : context->GetPaintRectWithTransform().GetOffset();
1870 auto parent = GetAncestorNodeOfFrame();
1871 while (parent) {
1872 auto renderContext = parent->GetRenderContext();
1873 CHECK_NULL_RETURN(renderContext, OffsetF());
1874 offset += renderContext->GetPaintRectWithTransform().GetOffset();
1875 parent = parent->GetAncestorNodeOfFrame();
1876 }
1877 return offset;
1878 }
1879
GetParentGlobalOffsetDuringLayout() const1880 OffsetF FrameNode::GetParentGlobalOffsetDuringLayout() const
1881 {
1882 OffsetF offset {};
1883 auto parent = GetAncestorNodeOfFrame();
1884 while (parent) {
1885 offset += parent->geometryNode_->GetFrameOffset();
1886 parent = parent->GetAncestorNodeOfFrame();
1887 }
1888 return offset;
1889 }
1890
GetPaintRectGlobalOffsetWithTranslate(bool excludeSelf) const1891 OffsetF FrameNode::GetPaintRectGlobalOffsetWithTranslate(bool excludeSelf) const
1892 {
1893 auto context = GetRenderContext();
1894 CHECK_NULL_RETURN(context, OffsetF());
1895 OffsetF offset = excludeSelf ? OffsetF() : context->GetPaintRectWithTranslate().GetOffset();
1896 auto parent = GetAncestorNodeOfFrame();
1897 while (parent) {
1898 auto renderContext = parent->GetRenderContext();
1899 CHECK_NULL_RETURN(renderContext, OffsetF());
1900 offset += renderContext->GetPaintRectWithTranslate().GetOffset();
1901 parent = parent->GetAncestorNodeOfFrame();
1902 }
1903 return offset;
1904 }
1905
GetPaintRectOffsetToPage() const1906 OffsetF FrameNode::GetPaintRectOffsetToPage() const
1907 {
1908 auto context = GetRenderContext();
1909 CHECK_NULL_RETURN(context, OffsetF());
1910 OffsetF offset = context->GetPaintRectWithTransform().GetOffset();
1911 auto parent = GetAncestorNodeOfFrame();
1912 while (parent && parent->GetTag() != V2::PAGE_ETS_TAG) {
1913 auto renderContext = parent->GetRenderContext();
1914 CHECK_NULL_RETURN(renderContext, OffsetF());
1915 offset += renderContext->GetPaintRectWithTransform().GetOffset();
1916 parent = parent->GetAncestorNodeOfFrame();
1917 }
1918 return (parent && parent->GetTag() == V2::PAGE_ETS_TAG) ? offset : OffsetF();
1919 }
1920
GetViewPort() const1921 std::optional<RectF> FrameNode::GetViewPort() const
1922 {
1923 if (viewPort_.has_value()) {
1924 return viewPort_;
1925 }
1926 auto parent = GetAncestorNodeOfFrame();
1927 while (parent && parent->GetTag() != V2::PAGE_ETS_TAG) {
1928 auto parentViewPort = parent->GetSelfViewPort();
1929 if (parentViewPort.has_value()) {
1930 return parentViewPort;
1931 }
1932 parent = parent->GetAncestorNodeOfFrame();
1933 }
1934 return std::nullopt;
1935 }
1936
OnNotifyMemoryLevel(int32_t level)1937 void FrameNode::OnNotifyMemoryLevel(int32_t level)
1938 {
1939 pattern_->OnNotifyMemoryLevel(level);
1940 }
1941
GetAllDepthChildrenCount()1942 int32_t FrameNode::GetAllDepthChildrenCount()
1943 {
1944 int32_t result = 0;
1945 std::list<RefPtr<FrameNode>> children;
1946 children.emplace_back(Claim(this));
1947 while (!children.empty()) {
1948 auto& node = children.front();
1949 if (!node->IsInternal()) {
1950 result++;
1951 node->GenerateOneDepthVisibleFrame(children);
1952 }
1953 children.pop_front();
1954 }
1955 return result;
1956 }
1957
OnAccessibilityEvent(AccessibilityEventType eventType,WindowsContentChangeTypes windowsContentChangeType) const1958 void FrameNode::OnAccessibilityEvent(
1959 AccessibilityEventType eventType, WindowsContentChangeTypes windowsContentChangeType) const
1960 {
1961 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
1962 AccessibilityEvent event;
1963 event.type = eventType;
1964 event.windowContentChangeTypes = windowsContentChangeType;
1965 event.nodeId = GetAccessibilityId();
1966 auto pipeline = PipelineContext::GetCurrentContext();
1967 CHECK_NULL_VOID(pipeline);
1968 pipeline->SendEventToAccessibility(event);
1969 }
1970 }
1971
OnAccessibilityEvent(AccessibilityEventType eventType,std::string beforeText,std::string latestContent) const1972 void FrameNode::OnAccessibilityEvent(
1973 AccessibilityEventType eventType, std::string beforeText, std::string latestContent) const
1974 {
1975 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
1976 AccessibilityEvent event;
1977 event.type = eventType;
1978 event.nodeId = GetAccessibilityId();
1979 event.beforeText = beforeText;
1980 event.latestContent = latestContent;
1981 auto pipeline = PipelineContext::GetCurrentContext();
1982 CHECK_NULL_VOID(pipeline);
1983 pipeline->SendEventToAccessibility(event);
1984 }
1985 }
1986
MarkRemoving()1987 bool FrameNode::MarkRemoving()
1988 {
1989 bool pendingRemove = false;
1990 if (!layoutProperty_ || !geometryNode_) {
1991 return pendingRemove;
1992 }
1993
1994 isRemoving_ = true;
1995
1996 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
1997 if (geometryTransition != nullptr) {
1998 geometryTransition->Build(WeakClaim(this), false);
1999 pendingRemove = true;
2000 }
2001
2002 const auto& children = GetChildren();
2003 for (const auto& child : children) {
2004 pendingRemove = child->MarkRemoving() || pendingRemove;
2005 }
2006 return pendingRemove;
2007 }
2008
AddHotZoneRect(const DimensionRect & hotZoneRect) const2009 void FrameNode::AddHotZoneRect(const DimensionRect& hotZoneRect) const
2010 {
2011 auto gestureHub = GetOrCreateGestureEventHub();
2012 gestureHub->AddResponseRect(hotZoneRect);
2013 }
2014
RemoveLastHotZoneRect() const2015 void FrameNode::RemoveLastHotZoneRect() const
2016 {
2017 auto gestureHub = GetOrCreateGestureEventHub();
2018 gestureHub->RemoveLastResponseRect();
2019 }
2020
OnRemoveFromParent(bool allowTransition)2021 bool FrameNode::OnRemoveFromParent(bool allowTransition)
2022 {
2023 // kick out transition animation if needed, wont re-entry if already detached.
2024 DetachFromMainTree(!allowTransition);
2025 auto context = GetRenderContext();
2026 CHECK_NULL_RETURN(context, false);
2027 if (!allowTransition || RemoveImmediately()) {
2028 // directly remove, reset focusHub, parent and depth
2029 if (auto focusHub = GetFocusHub()) {
2030 focusHub->RemoveSelf();
2031 }
2032 ResetParent();
2033 return true;
2034 }
2035 // delayed remove, will move self into disappearing children
2036 return false;
2037 }
2038
FindChildByPosition(float x,float y)2039 RefPtr<FrameNode> FrameNode::FindChildByPosition(float x, float y)
2040 {
2041 std::map<int32_t, RefPtr<FrameNode>> hitFrameNodes;
2042 std::list<RefPtr<FrameNode>> children;
2043 GenerateOneDepthAllFrame(children);
2044 for (const auto& child : children) {
2045 auto geometryNode = child->GetGeometryNode();
2046 if (!geometryNode) {
2047 continue;
2048 }
2049
2050 auto globalFrameRect = geometryNode->GetFrameRect();
2051 globalFrameRect.SetOffset(child->GetOffsetRelativeToWindow());
2052
2053 if (globalFrameRect.IsInRegion(PointF(x, y))) {
2054 hitFrameNodes.insert(std::make_pair(child->GetDepth(), child));
2055 }
2056 }
2057
2058 if (hitFrameNodes.empty()) {
2059 return nullptr;
2060 }
2061
2062 return hitFrameNodes.rbegin()->second;
2063 }
2064
CreateAnimatablePropertyFloat(const std::string & propertyName,float value,const std::function<void (float)> & onCallbackEvent)2065 void FrameNode::CreateAnimatablePropertyFloat(
2066 const std::string& propertyName, float value, const std::function<void(float)>& onCallbackEvent)
2067 {
2068 auto context = GetRenderContext();
2069 CHECK_NULL_VOID(context);
2070 auto iter = nodeAnimatablePropertyMap_.find(propertyName);
2071 if (iter != nodeAnimatablePropertyMap_.end()) {
2072 LOGW("AnimatableProperty already exists!");
2073 return;
2074 }
2075 auto property = AceType::MakeRefPtr<NodeAnimatablePropertyFloat>(value, std::move(onCallbackEvent));
2076 context->AttachNodeAnimatableProperty(property);
2077 nodeAnimatablePropertyMap_.emplace(propertyName, property);
2078 }
2079
UpdateAnimatablePropertyFloat(const std::string & propertyName,float value)2080 void FrameNode::UpdateAnimatablePropertyFloat(const std::string& propertyName, float value)
2081 {
2082 auto iter = nodeAnimatablePropertyMap_.find(propertyName);
2083 if (iter == nodeAnimatablePropertyMap_.end()) {
2084 LOGW("AnimatableProperty not exists!");
2085 return;
2086 }
2087 auto property = AceType::DynamicCast<NodeAnimatablePropertyFloat>(iter->second);
2088 CHECK_NULL_VOID(property);
2089 property->Set(value);
2090 }
2091
CreateAnimatableArithmeticProperty(const std::string & propertyName,RefPtr<CustomAnimatableArithmetic> & value,std::function<void (const RefPtr<CustomAnimatableArithmetic> &)> & onCallbackEvent)2092 void FrameNode::CreateAnimatableArithmeticProperty(const std::string& propertyName,
2093 RefPtr<CustomAnimatableArithmetic>& value,
2094 std::function<void(const RefPtr<CustomAnimatableArithmetic>&)>& onCallbackEvent)
2095 {
2096 auto context = GetRenderContext();
2097 CHECK_NULL_VOID(context);
2098 auto iter = nodeAnimatablePropertyMap_.find(propertyName);
2099 if (iter != nodeAnimatablePropertyMap_.end()) {
2100 LOGW("AnimatableProperty already exists!");
2101 return;
2102 }
2103 auto property = AceType::MakeRefPtr<NodeAnimatableArithmeticProperty>(value, std::move(onCallbackEvent));
2104 context->AttachNodeAnimatableProperty(property);
2105 nodeAnimatablePropertyMap_.emplace(propertyName, property);
2106 }
2107
UpdateAnimatableArithmeticProperty(const std::string & propertyName,RefPtr<CustomAnimatableArithmetic> & value)2108 void FrameNode::UpdateAnimatableArithmeticProperty(
2109 const std::string& propertyName, RefPtr<CustomAnimatableArithmetic>& value)
2110 {
2111 auto iter = nodeAnimatablePropertyMap_.find(propertyName);
2112 if (iter == nodeAnimatablePropertyMap_.end()) {
2113 LOGW("AnimatableProperty not exists!");
2114 return;
2115 }
2116 auto property = AceType::DynamicCast<NodeAnimatableArithmeticProperty>(iter->second);
2117 CHECK_NULL_VOID(property);
2118 property->Set(value);
2119 }
2120
ProvideRestoreInfo()2121 std::string FrameNode::ProvideRestoreInfo()
2122 {
2123 return pattern_->ProvideRestoreInfo();
2124 }
2125
RemoveImmediately() const2126 bool FrameNode::RemoveImmediately() const
2127 {
2128 auto context = GetRenderContext();
2129 CHECK_NULL_RETURN(context, true);
2130 // has transition out animation, need to wait for animation end
2131 return !context->HasTransitionOutAnimation();
2132 }
2133
GetNodesById(const std::unordered_set<int32_t> & set)2134 std::vector<RefPtr<FrameNode>> FrameNode::GetNodesById(const std::unordered_set<int32_t>& set)
2135 {
2136 std::vector<RefPtr<FrameNode>> nodes;
2137 for (auto nodeId : set) {
2138 auto uiNode = ElementRegister::GetInstance()->GetUINodeById(nodeId);
2139 if (!uiNode) {
2140 continue;
2141 }
2142 auto frameNode = DynamicCast<FrameNode>(uiNode);
2143 if (frameNode) {
2144 nodes.emplace_back(frameNode);
2145 }
2146 }
2147 return nodes;
2148 }
2149
AddFRCSceneInfo(const std::string & name,float speed,SceneStatus status)2150 void FrameNode::AddFRCSceneInfo(const std::string& name, float speed, SceneStatus status)
2151 {
2152 // [PLANNING]: Frame Rate Controller(FRC):
2153 // Based on scene, speed and scene status, FrameRateRange will be sent to RSNode.
2154 }
2155
CheckSecurityComponentStatus(std::vector<RectF> & rect)2156 void FrameNode::CheckSecurityComponentStatus(std::vector<RectF>& rect)
2157 {
2158 auto paintRect = GetTransformRectRelativeToWindow();
2159 if (IsSecurityComponent()) {
2160 bypass_ = CheckRectIntersect(paintRect, rect);
2161 }
2162 for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
2163 const auto& child = iter->Upgrade();
2164 if (child) {
2165 child->CheckSecurityComponentStatus(rect);
2166 }
2167 }
2168 rect.push_back(paintRect);
2169 }
2170
CheckRectIntersect(const RectF & dest,std::vector<RectF> & origin)2171 bool FrameNode::CheckRectIntersect(const RectF& dest, std::vector<RectF>& origin)
2172 {
2173 for (auto originRect : origin) {
2174 if (originRect.IsInnerIntersectWith(dest)) {
2175 return true;
2176 }
2177 }
2178 return false;
2179 }
2180
HaveSecurityComponent()2181 bool FrameNode::HaveSecurityComponent()
2182 {
2183 if (IsSecurityComponent()) {
2184 return true;
2185 }
2186 for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
2187 const auto& child = iter->Upgrade();
2188 if (child && child->HaveSecurityComponent()) {
2189 return true;
2190 }
2191 }
2192 return false;
2193 }
2194
IsSecurityComponent()2195 bool FrameNode::IsSecurityComponent()
2196 {
2197 return GetTag() == V2::LOCATION_BUTTON_ETS_TAG || GetTag() == V2::PASTE_BUTTON_ETS_TAG ||
2198 GetTag() == V2::SAVE_BUTTON_ETS_TAG;
2199 }
2200
GetPercentSensitive()2201 void FrameNode::GetPercentSensitive()
2202 {
2203 auto res = layoutProperty_->GetPercentSensitive();
2204 if (res.first) {
2205 if (layoutAlgorithm_) {
2206 layoutAlgorithm_->SetPercentWidth(true);
2207 }
2208 }
2209 if (res.second) {
2210 if (layoutAlgorithm_) {
2211 layoutAlgorithm_->SetPercentHeight(true);
2212 }
2213 }
2214 }
2215
UpdatePercentSensitive()2216 void FrameNode::UpdatePercentSensitive()
2217 {
2218 auto res = layoutProperty_->UpdatePercentSensitive(
2219 layoutAlgorithm_->GetPercentHeight(), layoutAlgorithm_->GetPercentWidth());
2220 if (res.first) {
2221 auto parent = GetAncestorNodeOfFrame();
2222 if (parent && parent->layoutAlgorithm_) {
2223 parent->layoutAlgorithm_->SetPercentWidth(true);
2224 }
2225 }
2226 if (res.second) {
2227 auto parent = GetAncestorNodeOfFrame();
2228 if (parent && parent->layoutAlgorithm_) {
2229 parent->layoutAlgorithm_->SetPercentHeight(true);
2230 }
2231 }
2232 }
2233
2234 // This will call child and self measure process.
Measure(const std::optional<LayoutConstraintF> & parentConstraint)2235 void FrameNode::Measure(const std::optional<LayoutConstraintF>& parentConstraint)
2236 {
2237 if (!oldGeometryNode_) {
2238 oldGeometryNode_ = geometryNode_->Clone();
2239 }
2240 RestoreGeoState();
2241 pattern_->BeforeCreateLayoutWrapper();
2242 GetLayoutAlgorithm(true);
2243
2244 if (layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE) == VisibleType::GONE) {
2245 layoutAlgorithm_->SetSkipMeasure();
2246 layoutAlgorithm_->SetSkipLayout();
2247 geometryNode_->SetFrameSize(SizeF());
2248 isLayoutDirtyMarked_ = false;
2249 return;
2250 }
2251 if (!isActive_) {
2252 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
2253 }
2254
2255 if (layoutAlgorithm_->SkipMeasure()) {
2256 LOGD("%{public}s, depth: %{public}d: the layoutAlgorithm skip measure", GetTag().c_str(), GetDepth());
2257 isLayoutDirtyMarked_ = false;
2258 return;
2259 }
2260
2261 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
2262 if (geometryTransition != nullptr) {
2263 geometryTransition->WillLayout(Claim(this));
2264 }
2265 auto preConstraint = layoutProperty_->GetLayoutConstraint();
2266 auto contentConstraint = layoutProperty_->GetContentLayoutConstraint();
2267 layoutProperty_->BuildGridProperty(Claim(this));
2268
2269 if (parentConstraint) {
2270 ApplyConstraint(*parentConstraint);
2271 } else {
2272 CreateRootConstraint();
2273 }
2274
2275 layoutProperty_->UpdateContentConstraint();
2276 geometryNode_->UpdateMargin(layoutProperty_->CreateMargin());
2277 geometryNode_->UpdatePaddingWithBorder(layoutProperty_->CreatePaddingAndBorder());
2278
2279 isConstraintNotChanged_ = layoutProperty_->ConstraintEqual(preConstraint, contentConstraint);
2280
2281 LOGD("Measure: %{public}s, depth: %{public}d, Constraint: %{public}s", GetTag().c_str(), GetDepth(),
2282 layoutProperty_->GetLayoutConstraint()->ToString().c_str());
2283
2284 isLayoutDirtyMarked_ = false;
2285
2286 if (isConstraintNotChanged_) {
2287 if (!CheckNeedForceMeasureAndLayout()) {
2288 ACE_SCOPED_TRACE("SkipMeasure");
2289 LOGD("%{public}s (depth: %{public}d) skip measure content", GetTag().c_str(), GetDepth());
2290 layoutAlgorithm_->SetSkipMeasure();
2291 return;
2292 }
2293 }
2294
2295 auto size = layoutAlgorithm_->MeasureContent(layoutProperty_->CreateContentConstraint(), this);
2296 if (size.has_value()) {
2297 geometryNode_->SetContentSize(size.value());
2298 }
2299 GetPercentSensitive();
2300 layoutAlgorithm_->Measure(this);
2301 if (overlayNode_) {
2302 overlayNode_->Measure(layoutProperty_->CreateChildConstraint());
2303 }
2304 UpdatePercentSensitive();
2305 // check aspect radio.
2306 if (pattern_ && pattern_->IsNeedAdjustByAspectRatio()) {
2307 const auto& magicItemProperty = layoutProperty_->GetMagicItemProperty();
2308 auto aspectRatio = magicItemProperty->GetAspectRatioValue();
2309 // Adjust by aspect ratio, firstly pick height based on width. It means that when width, height and
2310 // aspectRatio are all set, the height is not used.
2311 auto width = geometryNode_->GetFrameSize().Width();
2312 LOGD("aspect ratio affects, origin width: %{public}f, height: %{public}f", width,
2313 geometryNode_->GetFrameSize().Height());
2314 auto height = width / aspectRatio;
2315 LOGD("aspect ratio affects, new width: %{public}f, height: %{public}f", width, height);
2316 geometryNode_->SetFrameSize(SizeF({ width, height }));
2317 }
2318
2319 LOGD("on Measure Done: type: %{public}s, depth: %{public}d, Size: %{public}s", GetTag().c_str(), GetDepth(),
2320 geometryNode_->GetFrameSize().ToString().c_str());
2321
2322 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_LAYOUT);
2323 }
2324
2325 // Called to perform layout children.
Layout()2326 void FrameNode::Layout()
2327 {
2328 int64_t time = GetSysTimestamp();
2329 OffsetNodeToSafeArea();
2330 if (CheckNeedLayout(layoutProperty_->GetPropertyChangeFlag())) {
2331 if (!layoutProperty_->GetLayoutConstraint()) {
2332 const auto& parentLayoutConstraint = geometryNode_->GetParentLayoutConstraint();
2333 if (parentLayoutConstraint) {
2334 layoutProperty_->UpdateLayoutConstraint(parentLayoutConstraint.value());
2335 } else {
2336 LayoutConstraintF layoutConstraint;
2337 layoutConstraint.percentReference.SetWidth(PipelineContext::GetCurrentRootWidth());
2338 layoutConstraint.percentReference.SetHeight(PipelineContext::GetCurrentRootHeight());
2339 layoutProperty_->UpdateLayoutConstraint(layoutConstraint);
2340 }
2341 layoutProperty_->UpdateContentConstraint();
2342 }
2343 GetLayoutAlgorithm()->Layout(this);
2344 if (overlayNode_) {
2345 LayoutOverlay();
2346 }
2347 time = GetSysTimestamp() - time;
2348 AddNodeFlexLayouts();
2349 AddNodeLayoutTime(time);
2350 } else {
2351 GetLayoutAlgorithm()->SetSkipLayout();
2352 }
2353
2354 SaveGeoState();
2355 AvoidKeyboard();
2356 ExpandSafeArea();
2357
2358 LOGD("On Layout Done: type: %{public}s, depth: %{public}d, Offset: %{public}s", GetTag().c_str(), GetDepth(),
2359 geometryNode_->GetFrameOffset().ToString().c_str());
2360 SyncGeometryNode();
2361 }
2362
SyncGeometryNode()2363 void FrameNode::SyncGeometryNode()
2364 {
2365 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
2366 bool hasTransition = geometryTransition != nullptr && geometryTransition->IsRunning();
2367
2368 if (!isActive_ && !hasTransition) {
2369 LOGD("current node is inactive, don't need to render");
2370 layoutAlgorithm_.Reset();
2371 return;
2372 }
2373
2374 // update layout size.
2375 bool frameSizeChange = true;
2376 bool frameOffsetChange = true;
2377 bool contentSizeChange = true;
2378 bool contentOffsetChange = true;
2379 if (oldGeometryNode_) {
2380 frameSizeChange = geometryNode_->GetFrameSize() != oldGeometryNode_->GetFrameSize();
2381 frameOffsetChange = geometryNode_->GetFrameOffset() != oldGeometryNode_->GetFrameOffset();
2382 contentSizeChange = geometryNode_->GetContentSize() != oldGeometryNode_->GetContentSize();
2383 contentOffsetChange = geometryNode_->GetContentOffset() != oldGeometryNode_->GetContentOffset();
2384 oldGeometryNode_.Reset();
2385 }
2386
2387 // clean layout flag.
2388 layoutProperty_->CleanDirty();
2389
2390 if (hasTransition) {
2391 geometryTransition->DidLayout(Claim(this));
2392 } else if (frameSizeChange || frameOffsetChange || HasPositionProp() ||
2393 (pattern_->GetContextParam().has_value() && contentSizeChange)) {
2394 renderContext_->SyncGeometryProperties(RawPtr(geometryNode_));
2395 }
2396
2397 DirtySwapConfig config { frameSizeChange, frameOffsetChange, contentSizeChange, contentOffsetChange };
2398 // check if need to paint content.
2399 auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(layoutAlgorithm_);
2400 CHECK_NULL_VOID(layoutAlgorithmWrapper);
2401 config.skipMeasure = layoutAlgorithmWrapper->SkipMeasure();
2402 config.skipLayout = layoutAlgorithmWrapper->SkipLayout();
2403 if (!config.skipMeasure && !config.skipLayout && GetInspectorId()) {
2404 auto pipeline = PipelineContext::GetCurrentContext();
2405 CHECK_NULL_VOID(pipeline);
2406 pipeline->OnLayoutCompleted(GetInspectorId()->c_str());
2407 }
2408 auto needRerender = pattern_->OnDirtyLayoutWrapperSwap(Claim(this), config);
2409 // TODO: temp use and need to delete.
2410 needRerender =
2411 needRerender || pattern_->OnDirtyLayoutWrapperSwap(Claim(this), config.skipMeasure, config.skipLayout);
2412 if (needRerender || CheckNeedRender(paintProperty_->GetPropertyChangeFlag())) {
2413 MarkDirtyNode(true, true, PROPERTY_UPDATE_RENDER);
2414 }
2415
2416 // update border.
2417 if (layoutProperty_->GetBorderWidthProperty()) {
2418 if (!renderContext_->HasBorderColor()) {
2419 BorderColorProperty borderColorProperty;
2420 borderColorProperty.SetColor(Color::BLACK);
2421 renderContext_->UpdateBorderColor(borderColorProperty);
2422 }
2423 if (!renderContext_->HasBorderStyle()) {
2424 BorderStyleProperty borderStyleProperty;
2425 borderStyleProperty.SetBorderStyle(BorderStyle::SOLID);
2426 renderContext_->UpdateBorderStyle(borderStyleProperty);
2427 }
2428 if (layoutProperty_->GetLayoutConstraint().has_value()) {
2429 renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
2430 ScaleProperty::CreateScaleProperty(),
2431 layoutProperty_->GetLayoutConstraint()->percentReference.Width()));
2432 } else {
2433 renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
2434 ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth()));
2435 }
2436 }
2437
2438 // update background
2439 if (builderFunc_) {
2440 auto builderNode = builderFunc_();
2441 auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
2442 AceType::MakeRefPtr<LinearLayoutPattern>(true));
2443 builderNode->MountToParent(columnNode);
2444 SetBackgroundLayoutConstraint(columnNode);
2445 renderContext_->CreateBackgroundPixelMap(columnNode);
2446 builderFunc_ = nullptr;
2447 backgroundNode_ = columnNode;
2448 }
2449
2450 // update focus state
2451 auto focusHub = GetFocusHub();
2452 if (focusHub && focusHub->IsCurrentFocus()) {
2453 focusHub->ClearFocusState(false);
2454 focusHub->PaintFocusState(false);
2455 }
2456
2457 // rebuild child render node.
2458 RebuildRenderContextTree();
2459
2460 /* Adjust components' position which have been set grid properties */
2461 AdjustGridOffset();
2462
2463 layoutAlgorithm_.Reset();
2464 }
2465
GetOrCreateChildByIndex(uint32_t index,bool addToRenderTree)2466 RefPtr<LayoutWrapper> FrameNode::GetOrCreateChildByIndex(uint32_t index, bool addToRenderTree)
2467 {
2468 auto child = frameProxy_->GetFrameNodeByIndex(index, true);
2469 if (addToRenderTree && child) {
2470 child->SetActive(true);
2471 }
2472 return child;
2473 }
2474
GetChildByIndex(uint32_t index)2475 RefPtr<LayoutWrapper> FrameNode::GetChildByIndex(uint32_t index)
2476 {
2477 return frameProxy_->GetFrameNodeByIndex(index, false);
2478 }
2479
GetAllChildrenWithBuild(bool addToRenderTree)2480 const std::list<RefPtr<LayoutWrapper>>& FrameNode::GetAllChildrenWithBuild(bool addToRenderTree)
2481 {
2482 const auto& children = frameProxy_->GetAllFrameChildren();
2483 if (addToRenderTree) {
2484 for (const auto& child : children) {
2485 child->SetActive(true);
2486 }
2487 }
2488
2489 return children;
2490 }
2491
RemoveAllChildInRenderTree()2492 void FrameNode::RemoveAllChildInRenderTree()
2493 {
2494 frameProxy_->RemoveAllChildInRenderTree();
2495 }
2496
RemoveChildInRenderTree(uint32_t index)2497 void FrameNode::RemoveChildInRenderTree(uint32_t index)
2498 {
2499 frameProxy_->RemoveChildInRenderTree(index);
2500 }
2501
SkipMeasureContent() const2502 bool FrameNode::SkipMeasureContent() const
2503 {
2504 return layoutAlgorithm_->SkipMeasure();
2505 }
2506
CheckNeedForceMeasureAndLayout()2507 bool FrameNode::CheckNeedForceMeasureAndLayout()
2508 {
2509 PropertyChangeFlag flag = layoutProperty_->GetPropertyChangeFlag();
2510 return CheckNeedMeasure(flag) || CheckNeedLayout(flag);
2511 }
2512
GetBaselineDistance() const2513 float FrameNode::GetBaselineDistance() const
2514 {
2515 auto children = frameProxy_->GetAllFrameChildren();
2516 if (children.empty()) {
2517 return geometryNode_->GetBaselineDistance();
2518 }
2519 float distance = 0.0;
2520 for (const auto& child : children) {
2521 float childBaseline = child->GetBaselineDistance();
2522 distance = NearZero(distance) ? childBaseline : std::min(distance, childBaseline);
2523 }
2524 return distance;
2525 }
2526
MarkNeedSyncRenderTree(bool needRebuild)2527 void FrameNode::MarkNeedSyncRenderTree(bool needRebuild)
2528 {
2529 if (needRebuild) {
2530 frameProxy_->ResetChildren(true);
2531 }
2532 needSyncRenderTree_ = true;
2533 }
2534
GetFrameChildByIndex(uint32_t index,bool needBuild)2535 RefPtr<UINode> FrameNode::GetFrameChildByIndex(uint32_t index, bool needBuild)
2536 {
2537 if (index != 0) {
2538 return nullptr;
2539 }
2540 return Claim(this);
2541 }
2542
GetLayoutAlgorithm(bool needReset)2543 const RefPtr<LayoutAlgorithmWrapper>& FrameNode::GetLayoutAlgorithm(bool needReset)
2544 {
2545 if ((!layoutAlgorithm_ || (needReset && layoutAlgorithm_->IsExpire())) && pattern_) {
2546 layoutAlgorithm_ = MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm());
2547 }
2548 if (needReset) {
2549 layoutAlgorithm_->SetNeedMeasure();
2550 }
2551 return layoutAlgorithm_;
2552 }
2553
SetCacheCount(int32_t cacheCount,const std::optional<LayoutConstraintF> & itemConstraint)2554 void FrameNode::SetCacheCount(int32_t cacheCount, const std::optional<LayoutConstraintF>& itemConstraint)
2555 {
2556 frameProxy_->SetCacheCount(cacheCount, itemConstraint);
2557 }
2558
LayoutOverlay()2559 void FrameNode::LayoutOverlay()
2560 {
2561 auto size = geometryNode_->GetFrameSize();
2562 auto align = Alignment::TOP_LEFT;
2563 Dimension offsetX, offsetY;
2564 auto childLayoutProperty = overlayNode_->GetLayoutProperty();
2565 childLayoutProperty->GetOverlayOffset(offsetX, offsetY);
2566 auto offset = OffsetF(offsetX.ConvertToPx(), offsetY.ConvertToPx());
2567 if (childLayoutProperty->GetPositionProperty()) {
2568 align = childLayoutProperty->GetPositionProperty()->GetAlignment().value_or(align);
2569 }
2570
2571 auto childSize = overlayNode_->GetGeometryNode()->GetMarginFrameSize();
2572 auto translate = Alignment::GetAlignPosition(size, childSize, align) + offset;
2573 overlayNode_->GetGeometryNode()->SetMarginFrameOffset(translate);
2574 overlayNode_->Layout();
2575 }
2576
DoRemoveChildInRenderTree(uint32_t index,bool isAll)2577 void FrameNode::DoRemoveChildInRenderTree(uint32_t index, bool isAll)
2578 {
2579 isActive_ = false;
2580 }
2581
OnInspectorIdUpdate(const std::string &)2582 void FrameNode::OnInspectorIdUpdate(const std::string& /*unused*/)
2583 {
2584 auto parent = GetAncestorNodeOfFrame();
2585 CHECK_NULL_VOID_NOLOG(parent);
2586 if (parent->GetTag() == V2::RELATIVE_CONTAINER_ETS_TAG) {
2587 parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
2588 }
2589 }
2590
2591 } // namespace OHOS::Ace::NG
2592