1 /*
2 * Copyright (c) 2022-2025 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 "core/components_ng/base/node_render_status_monitor.h"
19 #include "core/components_ng/event/event_constants.h"
20 #include "core/components_ng/layout/layout_algorithm.h"
21 #include "core/components_ng/render/paint_wrapper.h"
22 #include "core/pipeline/base/element_register.h"
23
24 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
25 #include "core/common/layout_inspector.h"
26 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
27 #include "core/components_ng/pattern/web/web_pattern.h"
28 #endif
29 #include "ui/view/frame_node.h"
30 #include "ui/view/pattern.h"
31
32 #include "base/geometry/ng/offset_t.h"
33 #include "base/geometry/ng/point_t.h"
34 #include "base/log/ace_performance_monitor.h"
35 #include "base/log/ace_trace.h"
36 #include "base/log/event_report.h"
37 #include "base/log/dump_log.h"
38 #include "base/log/log_wrapper.h"
39 #include "base/memory/ace_type.h"
40 #include "base/memory/referenced.h"
41 #include "base/thread/cancelable_callback.h"
42 #include "base/thread/task_executor.h"
43 #include "base/utils/multi_thread.h"
44 #include "base/utils/system_properties.h"
45 #include "base/utils/time_util.h"
46 #include "base/utils/utils.h"
47 #include "core/common/ace_application_info.h"
48 #include "core/common/container.h"
49 #include "core/common/recorder/event_recorder.h"
50 #include "core/common/recorder/node_data_cache.h"
51 #include "core/components_ng/manager/drag_drop/drag_drop_related_configuration.h"
52 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
53 #include "core/components_ng/pattern/stage/page_pattern.h"
54 #include "core/components_ng/property/measure_utils.h"
55 #ifdef WINDOW_SCENE_SUPPORTED
56 #include "core/components_ng/pattern/ui_extension/dynamic_component/dynamic_component_manager.h"
57 #endif
58 #include "core/components_ng/syntax/lazy_for_each_node.h"
59 #include "core/components_ng/syntax/repeat_virtual_scroll_node.h"
60 #include "core/components_ng/syntax/repeat_virtual_scroll_2_node.h"
61
62 namespace {
63 constexpr double VISIBLE_RATIO_MIN = 0.0;
64 constexpr double VISIBLE_RATIO_MAX = 1.0;
65 constexpr int32_t SUBSTR_LENGTH = 3;
66 const char DIMENSION_UNIT_VP[] = "vp";
67 constexpr int32_t SIZE_CHANGE_DUMP_SIZE = 5;
68 constexpr double MIN_WIDTH = 5.0;
69 constexpr double MIN_HEIGHT = 5.0;
70 constexpr double MIN_OPACITY = 0.1;
71 constexpr uint64_t MATRIX_CACHE_TIME_THRESHOLD = 15000000000;
72 /* suggestOpIncByte_s status mask, to indicate different aspects of node status
73 * related with suggestion OPINC improvements.
74 * for internal use; subject to change.
75 */
76 // suggest opinc marked.
77 constexpr uint8_t SUGGEST_OPINC_MARKED_MASK = 1;
78 // Whether the node can be suggest opinc marked.
79 constexpr uint8_t CAN_SUGGEST_OPINC_MASK = 1 << 1;
80 // The node already activated for suggest opinc.
81 constexpr uint8_t SUGGEST_OPINC_ACTIVATED_ONCE = 1 << 2;
82 // The node already checked for suggest opinc.
83 constexpr uint8_t SUGGEST_OPINC_CHCKED_ONCE = 1 << 3;
84 // The node has checked through for lazy new nodes.
85 constexpr uint8_t SUGGEST_OPINC_CHECKED_THROUGH = 1 << 4;
86 // Node has rendergroup marked.
87 constexpr uint8_t APP_RENDER_GROUP_MARKED_MASK = 1 << 7;
88 // OPINC max ratio for scroll scope(height);
89 constexpr float HIGHT_RATIO_LIMIT = 0.8f;
90 // OPINC max ratio for scroll scope(width);
91 constexpr float WIDTH_RATIO_LIMIT = 1.0f;
92 // Min area for OPINC
93 constexpr int32_t MIN_OPINC_AREA = 10000;
94 } // namespace
95 namespace OHOS::Ace::NG {
96 namespace {
ClearAccessibilityFocus(const RefPtr<AccessibilityProperty> & accessibilityProperty,const RefPtr<RenderContext> & renderContext)97 void ClearAccessibilityFocus(const RefPtr<AccessibilityProperty>& accessibilityProperty,
98 const RefPtr<RenderContext>& renderContext)
99 {
100 CHECK_NULL_VOID(accessibilityProperty);
101 CHECK_NULL_VOID(renderContext);
102 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled() &&
103 accessibilityProperty->GetAccessibilityFocusState()) {
104 accessibilityProperty->SetAccessibilityFocusState(false);
105 if (renderContext->GetAccessibilityFocus().value_or(false)) {
106 renderContext->UpdateAccessibilityFocus(false);
107 }
108 }
109 }
110 } // namespace
111
112 class FrameNode::FrameProxy final : public RecursiveLock {
113 public:
114 struct FrameChildNode {
115 RefPtr<UINode> node;
116 uint32_t startIndex = 0;
117 uint32_t count = 0;
118 };
119
Lock()120 void Lock() override
121 {
122 ++inUse_;
123 }
124
Unlock()125 void Unlock() override
126 {
127 --inUse_;
128 if (!inUse_ && delayReset_) {
129 auto it = &hostNode_->frameProxy_;
130 while ((*it)) {
131 if (this == (*it)->prevFrameProxy_.get()) {
132 auto me = std::move((*it)->prevFrameProxy_);
133 (*it)->prevFrameProxy_ = std::move(me->prevFrameProxy_);
134 break;
135 }
136 it = &(*it)->prevFrameProxy_;
137 }
138 }
139 }
140
GetGuard()141 RecursionGuard GetGuard()
142 {
143 return RecursionGuard(*this);
144 }
145
FrameProxy(FrameNode * frameNode)146 explicit FrameProxy(FrameNode* frameNode) : hostNode_(frameNode)
147 {
148 prevFrameProxy_ = std::move(hostNode_->frameProxy_);
149 if (prevFrameProxy_ && !prevFrameProxy_->needResetChild_) {
150 children_ = prevFrameProxy_->children_;
151 cursor_ = children_.end();
152 if (prevFrameProxy_->cursor_ != prevFrameProxy_->children_.end()) {
153 cursor_ = std::find_if(children_.begin(), children_.end(),
154 [this](FrameChildNode& node) { return prevFrameProxy_->cursor_->node == node.node; });
155 }
156 }
157 }
158
Build()159 void Build()
160 {
161 if (hostNode_ == nullptr || !children_.empty()) {
162 return;
163 }
164 totalCount_ = 0;
165 const auto& children = hostNode_->GetChildren();
166 int32_t startIndex = 0;
167 int32_t count = 0;
168 for (const auto& child : children) {
169 count = child->FrameCount();
170 child->SetNodeIndexOffset(startIndex, count);
171 children_.push_back({ child, startIndex, count });
172 startIndex += count;
173 totalCount_ += count;
174 }
175 cursor_ = children_.begin();
176 }
177
AddFrameNode(const RefPtr<UINode> & UiNode,std::list<RefPtr<LayoutWrapper>> & allFrameNodeChildren,std::map<uint32_t,RefPtr<LayoutWrapper>> & partFrameNodeChildren,uint32_t & count)178 static void AddFrameNode(const RefPtr<UINode>& UiNode, std::list<RefPtr<LayoutWrapper>>& allFrameNodeChildren,
179 std::map<uint32_t, RefPtr<LayoutWrapper>>& partFrameNodeChildren, uint32_t& count)
180 {
181 auto frameNode = AceType::DynamicCast<FrameNode>(UiNode);
182 if (frameNode) {
183 allFrameNodeChildren.emplace_back(frameNode);
184 partFrameNodeChildren[count++] = frameNode;
185 return;
186 }
187 auto lazyForEachNode = AceType::DynamicCast<LazyForEachNode>(UiNode);
188 auto repeatVirtualScrollNode = AceType::DynamicCast<RepeatVirtualScrollNode>(UiNode);
189 auto repeatVirtualScroll2Node = AceType::DynamicCast<RepeatVirtualScroll2Node>(UiNode);
190 if (lazyForEachNode) {
191 lazyForEachNode->BuildAllChildren();
192 } else if (repeatVirtualScrollNode || repeatVirtualScroll2Node) {
193 TAG_LOGE(AceLogTag::ACE_REPEAT, "repeatVirtualScroll not support in non scoll container!");
194 } else {
195 auto customNode = AceType::DynamicCast<CustomNode>(UiNode);
196 if (customNode) {
197 customNode->Render();
198 }
199 }
200 for (const auto& child : UiNode->GetChildren()) {
201 auto frameNode = AceType::DynamicCast<FrameNode>(child);
202 if (frameNode) {
203 allFrameNodeChildren.emplace_back(frameNode);
204 partFrameNodeChildren[count++] = frameNode;
205 continue;
206 }
207 AddFrameNode(child, allFrameNodeChildren, partFrameNodeChildren, count);
208 }
209 }
210
GetAllFrameChildren()211 ChildrenListWithGuard GetAllFrameChildren()
212 {
213 auto guard = GetGuard();
214 if (allFrameNodeChildren_.empty()) {
215 Build();
216 uint32_t count = 0;
217 for (const auto& child : children_) {
218 AddFrameNode(child.node, allFrameNodeChildren_, partFrameNodeChildren_, count);
219 }
220 }
221 return ChildrenListWithGuard(allFrameNodeChildren_, *this);
222 }
223
FindFrameNodeByIndex(uint32_t index,bool needBuild,bool isCache,bool addToRenderTree)224 RefPtr<LayoutWrapper> FindFrameNodeByIndex(uint32_t index, bool needBuild, bool isCache, bool addToRenderTree)
225 {
226 while (cursor_ != children_.end()) {
227 if (cursor_->startIndex > index) {
228 cursor_--;
229 continue;
230 }
231
232 if (cursor_->startIndex + cursor_->count > index) {
233 auto frameNode = AceType::DynamicCast<FrameNode>(cursor_->node->GetFrameChildByIndex(
234 index - cursor_->startIndex, needBuild, isCache, addToRenderTree));
235 return frameNode;
236 }
237 cursor_++;
238 if (cursor_ == children_.end()) {
239 cursor_ = children_.begin();
240 return nullptr;
241 }
242 }
243 return nullptr;
244 }
245
GetFrameNodeByIndex(uint32_t index,bool needBuild,bool isCache,bool addToRenderTree)246 RefPtr<LayoutWrapper> GetFrameNodeByIndex(uint32_t index, bool needBuild, bool isCache, bool addToRenderTree)
247 {
248 auto itor = partFrameNodeChildren_.find(index);
249 if (itor == partFrameNodeChildren_.end()) {
250 Build();
251 auto child = FindFrameNodeByIndex(index, needBuild, isCache, addToRenderTree);
252 if (child && !isCache) {
253 partFrameNodeChildren_[index] = child;
254 }
255 return child;
256 }
257 return itor->second;
258 }
259
260 /**
261 * @brief Find child's index in parent's map. Only works on children that are already created and recorded.
262 *
263 * @param target child LayoutWrapper
264 * @return index of children
265 */
GetChildIndex(const RefPtr<LayoutWrapper> & target) const266 int32_t GetChildIndex(const RefPtr<LayoutWrapper>& target) const
267 {
268 for (auto it : partFrameNodeChildren_) {
269 if (it.second == target) {
270 return it.first;
271 }
272 }
273 return -1;
274 }
275
ResetChildren(bool needResetChild=false)276 void ResetChildren(bool needResetChild = false)
277 {
278 if (inUse_) {
279 if (SystemProperties::GetLayoutDetectEnabled()) {
280 LOGF_ABORT("[%{public}d:%{public}s] reset children while in use",
281 hostNode_->GetId(), hostNode_->GetTag().c_str());
282 } else {
283 LOGW("[%{public}d:%{public}s] reset children while in use",
284 hostNode_->GetId(), hostNode_->GetTag().c_str());
285 }
286 delayReset_ = true;
287 needResetChild_ = needResetChild;
288 hostNode_->frameProxy_ = std::make_unique<FrameProxy>(hostNode_);
289 return;
290 }
291 auto guard = GetGuard();
292 delayReset_ = false;
293 allFrameNodeChildren_.clear();
294 partFrameNodeChildren_.clear();
295 totalCount_ = 0;
296 if (needResetChild) {
297 children_.clear();
298 cursor_ = children_.begin();
299 }
300 }
301
RemoveChildInRenderTree(uint32_t index)302 void RemoveChildInRenderTree(uint32_t index)
303 {
304 auto itor = partFrameNodeChildren_.find(index);
305 if (itor == partFrameNodeChildren_.end()) {
306 return;
307 }
308 itor->second->SetActive(false);
309 partFrameNodeChildren_.erase(itor);
310 while (cursor_ != children_.end()) {
311 if (cursor_->startIndex > index) {
312 cursor_--;
313 continue;
314 }
315 if (cursor_->startIndex + cursor_->count > index) {
316 cursor_->node->DoRemoveChildInRenderTree(index - cursor_->startIndex);
317 return;
318 }
319 cursor_++;
320 if (cursor_ == children_.end()) {
321 cursor_ = children_.begin();
322 return;
323 }
324 }
325 }
326
SetActiveChildRange(int32_t start,int32_t end,int32_t cacheStart,int32_t cacheEnd,bool showCache=false)327 void SetActiveChildRange(int32_t start, int32_t end, int32_t cacheStart, int32_t cacheEnd, bool showCache = false)
328 {
329 int32_t startIndex = showCache ? start - cacheStart : start;
330 int32_t endIndex = showCache ? end + cacheEnd : end;
331 for (auto itor = partFrameNodeChildren_.begin(); itor != partFrameNodeChildren_.end();) {
332 int32_t index = itor->first;
333 if ((startIndex <= endIndex && index >= startIndex && index <= endIndex) ||
334 (startIndex > endIndex && (index <= endIndex || startIndex <= index))) {
335 itor++;
336 } else {
337 itor = partFrameNodeChildren_.erase(itor);
338 }
339 }
340 auto guard = GetGuard();
341 for (const auto& child : children_) {
342 child.node->DoSetActiveChildRange(
343 start - child.startIndex, end - child.startIndex, cacheStart, cacheEnd, showCache);
344 }
345 }
346
SetActiveChildRange(const std::optional<ActiveChildSets> & activeChildSets,const std::optional<ActiveChildRange> & activeChildRange)347 void SetActiveChildRange(
348 const std::optional<ActiveChildSets>& activeChildSets, const std::optional<ActiveChildRange>& activeChildRange)
349 {
350 if (!activeChildSets.has_value()) {
351 return;
352 }
353 for (auto itor = partFrameNodeChildren_.begin(); itor != partFrameNodeChildren_.end();) {
354 int32_t index = itor->first;
355 if (activeChildSets->activeItems.find(index) != activeChildSets->activeItems.end()) {
356 itor++;
357 } else {
358 itor = partFrameNodeChildren_.erase(itor);
359 }
360 }
361 auto guard = GetGuard();
362 // repeat node will use active node sets, V1 node(as lazyforeach) will still use active ndoe range.
363 for (const auto& child : children_) {
364 if (child.node->GetTag() == V2::JS_REPEAT_ETS_TAG) {
365 child.node->DoSetActiveChildRange(
366 activeChildSets->activeItems, activeChildSets->cachedItems, child.startIndex);
367 } else if (activeChildRange.has_value()) {
368 child.node->DoSetActiveChildRange(activeChildRange->start - child.startIndex,
369 activeChildRange->end - child.startIndex, activeChildRange->cacheStart, activeChildRange->cacheEnd);
370 }
371 }
372 }
373
RecycleItemsByIndex(uint32_t start,uint32_t end)374 void RecycleItemsByIndex(uint32_t start, uint32_t end)
375 {
376 for (auto it = partFrameNodeChildren_.begin(); it != partFrameNodeChildren_.end();) {
377 if (it->first >= start && it->first < end) {
378 it = partFrameNodeChildren_.erase(it);
379 } else {
380 it++;
381 }
382 }
383 }
384
RemoveAllChildInRenderTreeAfterReset()385 void RemoveAllChildInRenderTreeAfterReset()
386 {
387 Build();
388 auto guard = GetGuard();
389 for (const auto& child : children_) {
390 child.node->DoRemoveChildInRenderTree(0, true);
391 }
392 }
393
RemoveAllChildInRenderTree()394 void RemoveAllChildInRenderTree()
395 {
396 SetAllChildrenInactive();
397 ResetChildren();
398 hostNode_->frameProxy_->RemoveAllChildInRenderTreeAfterReset();
399 }
400
GetTotalCount()401 uint32_t GetTotalCount()
402 {
403 return totalCount_;
404 }
405
SetAllChildrenInactive()406 void SetAllChildrenInactive()
407 {
408 auto guard = GetGuard();
409 for (const auto& child : partFrameNodeChildren_) {
410 child.second->SetActive(false);
411 }
412 }
413
Dump()414 std::string Dump()
415 {
416 if (totalCount_ == 0) {
417 return "totalCount is 0";
418 }
419 std::string info = "FrameChildNode:[";
420 auto guard = GetGuard();
421 for (const auto& child : children_) {
422 info += std::to_string(child.node->GetId());
423 info += "-";
424 info += std::to_string(child.startIndex);
425 info += "-";
426 info += std::to_string(child.count);
427 info += ",";
428 }
429 info += "] partFrameNodeChildren:[";
430 for (const auto& child : partFrameNodeChildren_) {
431 info += std::to_string(child.second->GetHostNode()->GetId());
432 info += ",";
433 }
434 info += "] TotalCount:";
435 info += std::to_string(totalCount_);
436 return info;
437 }
438
SetCacheCount(int32_t cacheCount,const std::optional<LayoutConstraintF> & itemConstraint)439 void SetCacheCount(int32_t cacheCount, const std::optional<LayoutConstraintF>& itemConstraint)
440 {
441 auto guard = GetGuard();
442 for (const auto& child : children_) {
443 child.node->OnSetCacheCount(cacheCount, itemConstraint);
444 }
445 }
446
447 private:
448 std::list<FrameChildNode> children_;
449 std::list<FrameChildNode>::iterator cursor_ = children_.begin();
450 std::list<RefPtr<LayoutWrapper>> allFrameNodeChildren_;
451 std::map<uint32_t, RefPtr<LayoutWrapper>> partFrameNodeChildren_;
452 std::unique_ptr<FrameProxy> prevFrameProxy_;
453 int32_t totalCount_ = 0;
454 FrameNode* hostNode_ { nullptr };
455 uint32_t inUse_ = 0;
456 bool delayReset_ = false;
457 bool needResetChild_ = false;
458 }; // namespace OHOS::Ace::NG
459
FrameNode(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern,bool isRoot,bool isLayoutNode)460 FrameNode::FrameNode(
461 const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern, bool isRoot, bool isLayoutNode)
462 : UINode(tag, nodeId, isRoot), LayoutWrapper(WeakClaim(this)), pattern_(pattern)
463 {
464 isLayoutNode_ = isLayoutNode;
465 frameProxy_ = std::make_unique<FrameProxy>(this);
466 renderContext_->InitContext(IsRootNode(), pattern_->GetContextParam(), isLayoutNode);
467 paintProperty_ = pattern->CreatePaintProperty();
468 layoutProperty_ = pattern->CreateLayoutProperty();
469 accessibilityProperty_ = pattern->CreateAccessibilityProperty();
470 // first create make layout property dirty.
471 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
472 layoutProperty_->SetHost(WeakClaim(this));
473 layoutSeperately_ = true;
474 paintProperty_->SetHost(WeakClaim(this));
475 }
476
477
OnDelete()478 void FrameNode::OnDelete()
479 {
480 frameProxy_.reset();
481 nodeAnimatablePropertyMap_.clear();
482 UINode::OnDelete();
483 }
484
~FrameNode()485 FrameNode::~FrameNode()
486 {
487 ResetPredictNodes();
488 for (const auto& destroyCallback : destroyCallbacksMap_) {
489 if (destroyCallback.second) {
490 destroyCallback.second();
491 }
492 }
493 if (removeCustomProperties_) {
494 removeCustomProperties_();
495 removeCustomProperties_ = nullptr;
496 }
497
498 pattern_->DetachFromFrameNode(this);
499 if (IsOnMainTree()) {
500 OnDetachFromMainTree(false, GetContextWithCheck());
501 }
502 HandleAreaChangeDestruct();
503 CleanupPipelineResources();
504 FireOnNodeDestroyCallback();
505 FireOnExtraNodeDestroyCallback();
506 FireFrameNodeDestructorCallback();
507 if (kitNode_) {
508 kitNode_->Reset();
509 }
510 }
511
CreateEventHubInner()512 void FrameNode::CreateEventHubInner()
513 {
514 if (eventHub_ || !pattern_) {
515 return;
516 }
517 eventHub_ = pattern_->CreateEventHub();
518 if (eventHub_) {
519 eventHub_->AttachHost(WeakClaim(this));
520 }
521 }
522
CreateFrameNodeWithTree(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern)523 RefPtr<FrameNode> FrameNode::CreateFrameNodeWithTree(
524 const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern)
525 {
526 auto newChild = CreateFrameNode(tag, nodeId, pattern, true);
527 newChild->SetDepth(1);
528 return newChild;
529 }
530
GetOrCreateFrameNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)531 RefPtr<FrameNode> FrameNode::GetOrCreateFrameNode(
532 const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
533 {
534 auto frameNode = GetFrameNode(tag, nodeId);
535 if (frameNode) {
536 return frameNode;
537 }
538 auto pattern = patternCreator ? patternCreator() : MakeRefPtr<Pattern>();
539 return CreateFrameNode(tag, nodeId, pattern);
540 }
541
GetOrCreateCommonNode(const std::string & tag,int32_t nodeId,bool isLayoutNode,const std::function<RefPtr<Pattern> (void)> & patternCreator)542 RefPtr<FrameNode> FrameNode::GetOrCreateCommonNode(const std::string& tag, int32_t nodeId, bool isLayoutNode,
543 const std::function<RefPtr<Pattern>(void)>& patternCreator)
544 {
545 auto commonNode = GetFrameNode(tag, nodeId);
546 if (commonNode) {
547 commonNode->isLayoutNode_ = isLayoutNode;
548 return commonNode;
549 }
550 auto pattern = patternCreator ? patternCreator() : MakeRefPtr<Pattern>();
551 return CreateCommonNode(tag, nodeId, isLayoutNode, pattern);
552 }
553
GetFrameNode(const std::string & tag,int32_t nodeId)554 RefPtr<FrameNode> FrameNode::GetFrameNode(const std::string& tag, int32_t nodeId)
555 {
556 auto frameNode = ElementRegister::GetInstance()->GetSpecificItemById<FrameNode>(nodeId);
557 CHECK_NULL_RETURN(frameNode, nullptr);
558 if (frameNode->GetTag() != tag) {
559 ElementRegister::GetInstance()->RemoveItemSilently(nodeId);
560 auto parent = frameNode->GetParent();
561 if (parent) {
562 parent->RemoveChild(frameNode);
563 }
564 return nullptr;
565 }
566 return frameNode;
567 }
568
GetFrameNodeOnly(const std::string & tag,int32_t nodeId)569 RefPtr<FrameNode> FrameNode::GetFrameNodeOnly(const std::string& tag, int32_t nodeId)
570 {
571 auto frameNode = ElementRegister::GetInstance()->GetSpecificItemById<FrameNode>(nodeId);
572 CHECK_NULL_RETURN(frameNode, nullptr);
573 if (frameNode->GetTag() != tag) {
574 return nullptr;
575 }
576 return frameNode;
577 }
578
CreateFrameNode(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern,bool isRoot)579 RefPtr<FrameNode> FrameNode::CreateFrameNode(
580 const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern, bool isRoot)
581 {
582 auto frameNode = MakeRefPtr<FrameNode>(tag, nodeId, pattern, isRoot);
583 ElementRegister::GetInstance()->AddUINode(frameNode);
584 frameNode->InitializePatternAndContext();
585 return frameNode;
586 }
587
CreateCommonNode(const std::string & tag,int32_t nodeId,bool isLayoutNode,const RefPtr<Pattern> & pattern,bool isRoot)588 RefPtr<FrameNode> FrameNode::CreateCommonNode(
589 const std::string& tag, int32_t nodeId, bool isLayoutNode, const RefPtr<Pattern>& pattern, bool isRoot)
590 {
591 auto frameNode = MakeRefPtr<FrameNode>(tag, nodeId, pattern, isRoot, isLayoutNode);
592 ElementRegister::GetInstance()->AddUINode(frameNode);
593 frameNode->InitializePatternAndContext();
594 return frameNode;
595 }
596
GetIsLayoutNode()597 bool FrameNode::GetIsLayoutNode()
598 {
599 return isLayoutNode_;
600 }
601
GetIsFind()602 bool FrameNode::GetIsFind()
603 {
604 return isFind_;
605 }
606
SetIsFind(bool isFind)607 void FrameNode::SetIsFind(bool isFind)
608 {
609 isFind_ = isFind;
610 }
611
GetOneDepthVisibleFrame(std::list<RefPtr<FrameNode>> & children)612 void FrameNode::GetOneDepthVisibleFrame(std::list<RefPtr<FrameNode>>& children)
613 {
614 GenerateOneDepthVisibleFrameWithTransition(children);
615 if (overlayNode_) {
616 children.emplace_back(overlayNode_);
617 }
618 }
619
GetOneDepthVisibleFrameWithOffset(std::list<RefPtr<FrameNode>> & children,OffsetF & offset)620 void FrameNode::GetOneDepthVisibleFrameWithOffset(std::list<RefPtr<FrameNode>>& children, OffsetF& offset)
621 {
622 auto context = GetRenderContext();
623 CHECK_NULL_VOID(context);
624 offset += context->GetPaintRectWithoutTransform().GetOffset();
625 GenerateOneDepthVisibleFrameWithOffset(children, offset);
626 if (overlayNode_) {
627 children.emplace_back(overlayNode_);
628 }
629 }
630
IsSupportDrawModifier()631 bool FrameNode::IsSupportDrawModifier()
632 {
633 CHECK_NULL_RETURN(pattern_, false);
634 return pattern_->IsSupportDrawModifier();
635 }
636
ProcessOffscreenNode(const RefPtr<FrameNode> & node,bool needRemainActive)637 void FrameNode::ProcessOffscreenNode(const RefPtr<FrameNode>& node, bool needRemainActive)
638 {
639 CHECK_NULL_VOID(node);
640 if (node->GetRenderContext()) {
641 node->GetRenderContext()->SetDrawNode();
642 }
643 auto task = [weak = AceType::WeakClaim(AceType::RawPtr(node)), needRemainActive]() {
644 auto node = weak.Upgrade();
645 CHECK_NULL_VOID(node);
646 node->ProcessOffscreenTask();
647 node->MarkModifyDone();
648 node->UpdateLayoutPropertyFlag();
649 bool isActive = node->IsActive();
650 node->SetActive();
651 node->isLayoutDirtyMarked_ = true;
652 auto pipeline = node->GetContext();
653 if (pipeline) {
654 pipeline->FlushUITaskWithSingleDirtyNode(node);
655 }
656 auto predictLayoutNode = std::move(node->predictLayoutNode_);
657 for (auto& node : predictLayoutNode) {
658 auto frameNode = node.Upgrade();
659 if (frameNode && pipeline) {
660 pipeline->FlushUITaskWithSingleDirtyNode(frameNode);
661 }
662 }
663 if (pipeline) {
664 pipeline->FlushSyncGeometryNodeTasks();
665 }
666
667 auto paintProperty = node->GetPaintProperty<PaintProperty>();
668 auto wrapper = node->CreatePaintWrapper();
669 if (wrapper != nullptr) {
670 wrapper->FlushRender();
671 }
672 paintProperty->CleanDirty();
673 CHECK_NULL_VOID(pipeline);
674 pipeline->FlushModifier();
675 pipeline->FlushMessages();
676 if (needRemainActive) {
677 node->SetActive(isActive);
678 } else {
679 node->SetActive(false);
680 }
681 };
682 auto pipeline = node->GetContext();
683 if (pipeline && pipeline->IsLayouting()) {
684 pipeline->AddAfterLayoutTask(task);
685 return;
686 }
687 task();
688 }
689
InitializePatternAndContext()690 void FrameNode::InitializePatternAndContext()
691 {
692 pattern_->AttachToFrameNode(WeakClaim(this));
693 accessibilityProperty_->SetHost(WeakClaim(this));
694 renderContext_->SetRequestFrame([weak = WeakClaim(this)] {
695 auto frameNode = weak.Upgrade();
696 CHECK_NULL_VOID(frameNode);
697 if (frameNode->IsOnMainTree()) {
698 auto context = frameNode->GetContext();
699 CHECK_NULL_VOID(context);
700 context->RequestFrame();
701 return;
702 }
703 frameNode->hasPendingRequest_ = true;
704 });
705 renderContext_->SetHostNode(WeakClaim(this));
706 // Initialize FocusHub
707 if (pattern_->GetFocusPattern().GetFocusType() != FocusType::DISABLE) {
708 GetOrCreateFocusHub();
709 }
710 }
711
DumpLayoutInfo()712 void FrameNode::DumpLayoutInfo()
713 {
714 auto layoutInfoString = layoutProperty_->LayoutInfoToString();
715 if (!layoutInfoString.empty()) {
716 DumpLog::GetInstance().AddDesc(std::string("LayoutInfo: ").append(layoutInfoString.c_str()));
717 }
718 const auto& flexItemProperty = layoutProperty_->GetFlexItemProperty();
719 if (flexItemProperty) {
720 auto flexLayoutInfoString = flexItemProperty->FlexLayoutInfoToString();
721 if (!flexLayoutInfoString.empty()) {
722 DumpLog::GetInstance().AddDesc(std::string("FlexLayoutInfo: ").append(flexLayoutInfoString.c_str()));
723 }
724 }
725 }
726
DumpSafeAreaInfo()727 void FrameNode::DumpSafeAreaInfo()
728 {
729 auto&& opts = layoutProperty_->GetSafeAreaExpandOpts();
730 if (opts) {
731 DumpLog::GetInstance().AddDesc(
732 opts->ToString().append(",hostPageId: ").append(std::to_string(hostPageId_).c_str()));
733 }
734 auto&& ignoreLayoutSafeAreaOpts = layoutProperty_->GetIgnoreLayoutSafeAreaOpts();
735 if (ignoreLayoutSafeAreaOpts) {
736 DumpLog::GetInstance().AddDesc(ignoreLayoutSafeAreaOpts->ToString());
737 }
738 if (layoutProperty_->GetSafeAreaInsets()) {
739 DumpLog::GetInstance().AddDesc(layoutProperty_->GetSafeAreaInsets()->ToString());
740 }
741 if (SelfOrParentExpansive()) {
742 DumpLog::GetInstance().AddDesc(std::string("selfAdjust: ")
743 .append(geometryNode_->GetSelfAdjust().ToString().c_str())
744 .append(",parentAdjust: ")
745 .append(geometryNode_->GetParentAdjust().ToString().c_str()));
746 }
747 CHECK_NULL_VOID(tag_ == V2::PAGE_ETS_TAG);
748 auto pipeline = GetContext();
749 CHECK_NULL_VOID(pipeline);
750 auto manager = pipeline->GetSafeAreaManager();
751 CHECK_NULL_VOID(manager);
752 DumpLog::GetInstance().AddDesc(std::string("ignoreSafeArea: ")
753 .append(std::to_string(manager->IsIgnoreSafeArea()))
754 .append(std::string(", isNeedAvoidWindow: ").c_str())
755 .append(std::to_string(manager->IsNeedAvoidWindow()))
756 .append(std::string(", isFullScreen: ").c_str())
757 .append(std::to_string(manager->IsFullScreen()))
758 .append(std::string(", isKeyboardAvoidMode").c_str())
759 .append(std::to_string(static_cast<int32_t>(manager->GetKeyBoardAvoidMode())))
760 .append(std::string(", isUseCutout").c_str())
761 .append(std::to_string(manager->GetUseCutout())));
762 }
763
DumpAlignRulesInfo()764 void FrameNode::DumpAlignRulesInfo()
765 {
766 auto& flexItemProperties = layoutProperty_->GetFlexItemProperty();
767 CHECK_NULL_VOID(flexItemProperties);
768 auto rulesToString = flexItemProperties->AlignRulesToString();
769 CHECK_NULL_VOID(!rulesToString.empty());
770 DumpLog::GetInstance().AddDesc(std::string("AlignRules: ").append(rulesToString));
771 }
772
DumpExtensionHandlerInfo()773 void FrameNode::DumpExtensionHandlerInfo()
774 {
775 if (!extensionHandler_) {
776 return;
777 }
778 DumpLog::GetInstance().AddDesc(std::string("ExtensionHandler: HasCustomerMeasure: ")
779 .append(extensionHandler_->HasCustomerMeasure() ? "true" : "false")
780 .append(", HasCustomerLayout: ")
781 .append(extensionHandler_->HasCustomerLayout() ? "true" : "false"));
782 }
783
DumpCommonInfo()784 void FrameNode::DumpCommonInfo()
785 {
786 DumpLog::GetInstance().AddDesc(std::string("FrameRect: ").append(geometryNode_->GetFrameRect().ToString()));
787 DumpLog::GetInstance().AddDesc(
788 std::string("PaintRect without transform: ").append(renderContext_->GetPaintRectWithoutTransform().ToString()));
789 if (renderContext_->GetBackgroundColor()->ColorToString().compare("#00000000") != 0) {
790 DumpLog::GetInstance().AddDesc(
791 std::string("BackgroundColor: ").append(renderContext_->GetBackgroundColor()->ColorToString()));
792 }
793 if (geometryNode_->GetParentLayoutConstraint().has_value())
794 DumpLog::GetInstance().AddDesc(std::string("ParentLayoutConstraint: ")
795 .append(geometryNode_->GetParentLayoutConstraint().value().ToString()));
796 if (!(NearZero(GetOffsetRelativeToWindow().GetY()) && NearZero(GetOffsetRelativeToWindow().GetX()))) {
797 DumpLog::GetInstance().AddDesc(std::string("top: ")
798 .append(std::to_string(GetOffsetRelativeToWindow().GetY()))
799 .append(" left: ")
800 .append(std::to_string(GetOffsetRelativeToWindow().GetX())));
801 }
802 if (static_cast<int32_t>(IsActive()) != 1) {
803 DumpLog::GetInstance().AddDesc(
804 std::string("Active: ").append(std::to_string(static_cast<int32_t>(IsActive()))));
805 }
806 if (IsFreeze()) {
807 DumpLog::GetInstance().AddDesc(std::string("Freeze: 1"));
808 if (IsUserFreeze()) {
809 DumpLog::GetInstance().AddDesc(std::string("UserFreeze: 1"));
810 }
811 }
812 if (static_cast<int32_t>(layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)) != 0) {
813 DumpLog::GetInstance().AddDesc(std::string("Visible: ")
814 .append(std::to_string(static_cast<int32_t>(
815 layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)))));
816 }
817 if (layoutProperty_->GetPaddingProperty()) {
818 DumpLog::GetInstance().AddDesc(
819 std::string("Padding: ").append(layoutProperty_->GetPaddingProperty()->ToString().c_str()));
820 }
821 if (layoutProperty_->GetSafeAreaPaddingProperty()) {
822 DumpLog::GetInstance().AddDesc(std::string("SafeArea Padding: ")
823 .append(layoutProperty_->GetSafeAreaPaddingProperty()->ToString().c_str()));
824 }
825 if (layoutProperty_->GetBorderWidthProperty()) {
826 DumpLog::GetInstance().AddDesc(
827 std::string("Border: ").append(layoutProperty_->GetBorderWidthProperty()->ToString().c_str()));
828 }
829 if (renderContext_->HasBorderRadius()) {
830 DumpLog::GetInstance().AddDesc(
831 std::string("BorderRadius: ").append(renderContext_->GetBorderRadius()->ToString().c_str()));
832 }
833 if (layoutProperty_->GetMarginProperty()) {
834 DumpLog::GetInstance().AddDesc(
835 std::string("Margin: ").append(layoutProperty_->GetMarginProperty()->ToString().c_str()));
836 }
837 if (layoutProperty_->GetLayoutRect()) {
838 DumpLog::GetInstance().AddDesc(
839 std::string("LayoutRect: ").append(layoutProperty_->GetLayoutRect().value().ToString().c_str()));
840 }
841 DumpExtensionHandlerInfo();
842 DumpSafeAreaInfo();
843 if (layoutProperty_->GetCalcLayoutConstraint()) {
844 DumpLog::GetInstance().AddDesc(std::string("User defined constraint: ")
845 .append(layoutProperty_->GetCalcLayoutConstraint()->ToString().c_str()));
846 }
847 if (!propInspectorId_->empty()) {
848 DumpLog::GetInstance().AddDesc(std::string("compid: ").append(propInspectorId_.value_or("")));
849 }
850 if (layoutProperty_->GetPaddingProperty() || layoutProperty_->GetBorderWidthProperty() ||
851 layoutProperty_->GetMarginProperty() || layoutProperty_->GetCalcLayoutConstraint()) {
852 DumpLog::GetInstance().AddDesc(
853 std::string("ContentConstraint: ")
854 .append(layoutProperty_->GetContentLayoutConstraint().has_value()
855 ? layoutProperty_->GetContentLayoutConstraint().value().ToString()
856 : "NA"));
857 }
858 if (NearZero(renderContext_->GetZIndexValue(ZINDEX_DEFAULT_VALUE))) {
859 DumpLog::GetInstance().AddDesc(
860 std::string("zIndex: ").append(std::to_string(renderContext_->GetZIndexValue(ZINDEX_DEFAULT_VALUE))));
861 }
862 if (tag_ == V2::ROOT_ETS_TAG) {
863 auto pipeline = GetContext();
864 CHECK_NULL_VOID(pipeline);
865 DumpLog::GetInstance().AddDesc(std::string("dpi: ").append(std::to_string(pipeline->GetDensity())));
866 }
867 auto layoutPolicy = layoutProperty_->GetLayoutPolicyProperty();
868 if (layoutPolicy.has_value()) {
869 std::string layoutPolicyStr = layoutPolicy.value().ToString();
870 if (layoutPolicyStr.length() > 0) {
871 DumpLog::GetInstance().AddDesc(layoutPolicyStr);
872 }
873 }
874 DumpAlignRulesInfo();
875 DumpDragInfo();
876 DumpOverlayInfo();
877 DumpLayoutInfo();
878 if (frameProxy_->Dump().compare("totalCount is 0") != 0) {
879 DumpLog::GetInstance().AddDesc(std::string("FrameProxy: ").append(frameProxy_->Dump().c_str()));
880 }
881 if (isRemoving_) {
882 DumpLog::GetInstance().AddDesc(std::string("IsRemoving: True"));
883 }
884 }
885
DumpDragInfo()886 void FrameNode::DumpDragInfo()
887 {
888 DumpLog::GetInstance().AddDesc("------------start print dragInfo");
889 DumpLog::GetInstance().AddDesc(std::string("Draggable: ")
890 .append(draggable_ ? "true" : "false")
891 .append(" UserSet: ")
892 .append(userSet_ ? "true" : "false")
893 .append(" CustomerSet: ")
894 .append(customerSet_ ? "true" : "false"));
895 auto dragPreviewStr =
896 std::string("DragPreview: Has customNode: ").append(dragPreviewInfo_.customNode ? "YES" : "NO");
897 dragPreviewStr.append(" Has pixelMap: ").append(dragPreviewInfo_.pixelMap ? "YES" : "NO");
898 dragPreviewStr.append(" extraInfo: ").append(dragPreviewInfo_.extraInfo.c_str());
899 dragPreviewStr.append(" inspectorId: ").append(dragPreviewInfo_.inspectorId.c_str());
900 DumpLog::GetInstance().AddDesc(dragPreviewStr);
901 auto eventHub = GetEventHub<EventHub>();
902 DumpLog::GetInstance().AddDesc(std::string("Event: ")
903 .append("OnDragStart: ")
904 .append(eventHub && eventHub->HasOnDragStart() ? "YES" : "NO")
905 .append(" OnDragEnter: ")
906 .append(eventHub && eventHub->HasOnDragEnter() ? "YES" : "NO")
907 .append(" OnDragLeave: ")
908 .append(eventHub && eventHub->HasOnDragLeave() ? "YES" : "NO")
909 .append(" OnDragMove: ")
910 .append(eventHub && eventHub->HasOnDragMove() ? "YES" : "NO")
911 .append(" OnDrop: ")
912 .append(eventHub && eventHub->HasOnDrop() ? "YES" : "NO")
913 .append(" OnDragEnd: ")
914 .append(eventHub && eventHub->HasOnDragEnd() ? "YES" : "NO"));
915 DumpLog::GetInstance().AddDesc(std::string("DefaultOnDragStart: ")
916 .append(eventHub && eventHub->HasDefaultOnDragStart() ? "YES" : "NO")
917 .append(" CustomerOnDragEnter: ")
918 .append(eventHub && eventHub->HasCustomerOnDragEnter() ? "YES" : "NO")
919 .append(" CustomerOnDragLeave: ")
920 .append(eventHub && eventHub->HasCustomerOnDragLeave() ? "YES" : "NO")
921 .append(" CustomerOnDragMove: ")
922 .append(eventHub && eventHub->HasCustomerOnDragMove() ? "YES" : "NO")
923 .append(" CustomerOnDrop: ")
924 .append(eventHub && eventHub->HasCustomerOnDrop() ? "YES" : "NO")
925 .append(" CustomerOnDragEnd: ")
926 .append(eventHub && eventHub->HasCustomerOnDragEnd() ? "YES" : "NO"));
927 DumpLog::GetInstance().AddDesc("------------end print dragInfo");
928 }
929
DumpOnSizeChangeInfo()930 void FrameNode::DumpOnSizeChangeInfo()
931 {
932 for (auto it = onSizeChangeDumpInfos.rbegin(); it != onSizeChangeDumpInfos.rend(); ++it) {
933 DumpLog::GetInstance().AddDesc(std::string("onSizeChange Time: ")
934 .append(ConvertTimestampToStr(it->onSizeChangeTimeStamp))
935 .append(" lastFrameRect: ")
936 .append(it->lastFrameRect.ToString())
937 .append(" currFrameRect: ")
938 .append(it->currFrameRect.ToString()));
939 }
940 }
941
DumpKeyboardShortcutInfo()942 void FrameNode::DumpKeyboardShortcutInfo()
943 {
944 auto eventHub = GetEventHub<EventHub>();
945 if (!eventHub) {
946 return;
947 }
948 auto keyboardShortcuts = eventHub->GetKeyboardShortcut();
949 std::string result;
950 for (auto& keyboardShortcut : keyboardShortcuts) {
951 result.append("KeyboardShortcut: ")
952 .append("keys: ")
953 .append(std::to_string(keyboardShortcut.keys))
954 .append(" value: ")
955 .append(keyboardShortcut.value);
956 }
957 DumpLog::GetInstance().AddDesc(result);
958 }
959
DumpOverlayInfo()960 void FrameNode::DumpOverlayInfo()
961 {
962 if (!layoutProperty_->IsOverlayNode()) {
963 return;
964 }
965 DumpLog::GetInstance().AddDesc(std::string("IsOverlayNode: ").append(std::string("true")));
966 Dimension offsetX, offsetY;
967 layoutProperty_->GetOverlayOffset(offsetX, offsetY);
968 DumpLog::GetInstance().AddDesc(
969 std::string("OverlayOffset: ").append(offsetX.ToString()).append(std::string(", ")).append(offsetY.ToString()));
970 }
971
DumpSimplifyCommonInfo(std::shared_ptr<JsonValue> & json)972 void FrameNode::DumpSimplifyCommonInfo(std::shared_ptr<JsonValue>& json)
973 {
974 json->Put("$rect", GetTransformRectRelativeToWindow().ToBounds().c_str());
975 json->Put("$debugLine", "");
976 }
977
DumpPadding(const std::unique_ptr<NG::PaddingProperty> & padding,std::string label,std::unique_ptr<JsonValue> & json)978 void FrameNode::DumpPadding(const std::unique_ptr<NG::PaddingProperty>& padding, std::string label,
979 std::unique_ptr<JsonValue>& json)
980 {
981 CHECK_NULL_VOID(padding);
982 NG::CalcLength defaultValue = NG::CalcLength(
983 Dimension(0, padding->left.value_or(CalcLength()).GetDimension().Unit()));
984 if (padding->left.value_or(defaultValue) != defaultValue || padding->right.value_or(defaultValue) != defaultValue ||
985 padding->top.value_or(defaultValue) != defaultValue || padding->bottom.value_or(defaultValue) != defaultValue) {
986 json->Put(label.c_str(), padding->ToString().c_str());
987 }
988 }
989
DumpBorder(const std::unique_ptr<NG::BorderWidthProperty> & border,std::string label,std::unique_ptr<JsonValue> & json)990 void FrameNode::DumpBorder(const std::unique_ptr<NG::BorderWidthProperty>& border, std::string label,
991 std::unique_ptr<JsonValue>& json)
992 {
993 CHECK_NULL_VOID(border);
994 Dimension defaultValue(0, border->leftDimen.value_or(Dimension()).Unit());
995 if (border->leftDimen.value_or(defaultValue) != defaultValue ||
996 border->rightDimen.value_or(defaultValue) != defaultValue ||
997 border->topDimen.value_or(defaultValue) != defaultValue ||
998 border->bottomDimen.value_or(defaultValue) != defaultValue) {
999 json->Put(label.c_str(), border->ToString().c_str());
1000 }
1001 }
1002
DumpSimplifySafeAreaInfo(std::unique_ptr<JsonValue> & json)1003 void FrameNode::DumpSimplifySafeAreaInfo(std::unique_ptr<JsonValue>& json)
1004 {
1005 auto&& opts = layoutProperty_->GetSafeAreaExpandOpts();
1006 if (opts && (opts->type != NG::SAFE_AREA_TYPE_NONE || opts->edges != NG::SAFE_AREA_EDGE_NONE)) {
1007 json->Put("SafeAreaExpandOpts", opts->ToString().c_str());
1008 }
1009 if (layoutProperty_->GetSafeAreaInsets()) {
1010 json->Put("SafeAreaInsets", layoutProperty_->GetSafeAreaInsets()->ToString().c_str());
1011 }
1012 if (SelfOrParentExpansive()) {
1013 RectF defaultValue(0.0, 0.0, 0.0, 0.0);
1014 auto rect = geometryNode_->GetSelfAdjust();
1015 auto parentRect = geometryNode_->GetParentAdjust();
1016 if (rect != defaultValue) {
1017 json->Put("SelfAdjust", rect.ToString().c_str());
1018 }
1019 if (parentRect != defaultValue) {
1020 json->Put("ParentSelfAdjust", parentRect.ToString().c_str());
1021 }
1022 }
1023 CHECK_NULL_VOID(tag_ == V2::PAGE_ETS_TAG);
1024 auto pipeline = GetContext();
1025 CHECK_NULL_VOID(pipeline);
1026 auto manager = pipeline->GetSafeAreaManager();
1027 CHECK_NULL_VOID(manager);
1028 if (manager->KeyboardSafeAreaEnabled()) {
1029 json->Put("KeyboardInset: ", manager->GetKeyboardInset().ToString().c_str());
1030 }
1031 json->Put("IgnoreSafeArea", manager->IsIgnoreSafeArea());
1032 json->Put("IsNeedAvoidWindow", manager->IsNeedAvoidWindow());
1033 json->Put("IsFullScreen", manager->IsFullScreen());
1034 json->Put("IsKeyboardAvoidMode", static_cast<int32_t>(manager->GetKeyBoardAvoidMode()));
1035 json->Put("IsUseCutout", manager->GetUseCutout());
1036 }
1037
DumpSimplifyOverlayInfo(std::unique_ptr<JsonValue> & json)1038 void FrameNode::DumpSimplifyOverlayInfo(std::unique_ptr<JsonValue>& json)
1039 {
1040 if (!layoutProperty_->IsOverlayNode()) {
1041 return;
1042 }
1043 json->Put("IsOverlayNode", true);
1044 Dimension offsetX;
1045 Dimension offsetY;
1046 layoutProperty_->GetOverlayOffset(offsetX, offsetY);
1047 json->Put("OverlayOffset", (offsetX.ToString() + "," + offsetY.ToString()).c_str());
1048 }
1049
CheckVisibleOrActive()1050 bool FrameNode::CheckVisibleOrActive()
1051 {
1052 if (layoutTags_.find(tag_) != layoutTags_.end()) {
1053 return layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE) == VisibleType::VISIBLE && IsActive();
1054 } else {
1055 return true;
1056 }
1057 }
1058
DumpSimplifyInfo(std::shared_ptr<JsonValue> & json)1059 void FrameNode::DumpSimplifyInfo(std::shared_ptr<JsonValue>& json)
1060 {
1061 CHECK_NULL_VOID(json);
1062 DumpSimplifyCommonInfo(json);
1063 if (pattern_) {
1064 auto child = JsonUtil::CreateSharedPtrJson();
1065 pattern_->DumpSimplifyInfo(child);
1066 json->Put("$attrs", std::move(child));
1067 }
1068 }
1069
DumpInfo()1070 void FrameNode::DumpInfo()
1071 {
1072 DumpCommonInfo();
1073 DumpOnSizeChangeInfo();
1074 DumpKeyboardShortcutInfo();
1075 if (pattern_) {
1076 pattern_->DumpInfo();
1077 }
1078 if (renderContext_) {
1079 renderContext_->DumpInfo();
1080 }
1081 }
1082
DumpAdvanceInfo()1083 void FrameNode::DumpAdvanceInfo()
1084 {
1085 DumpCommonInfo();
1086 DumpOnSizeChangeInfo();
1087 DumpKeyboardShortcutInfo();
1088 if (pattern_) {
1089 pattern_->DumpInfo();
1090 pattern_->DumpAdvanceInfo();
1091 }
1092 if (renderContext_) {
1093 renderContext_->DumpInfo();
1094 renderContext_->DumpAdvanceInfo();
1095 }
1096 }
1097
DumpViewDataPageNode(RefPtr<ViewDataWrap> viewDataWrap,bool needsRecordData)1098 void FrameNode::DumpViewDataPageNode(RefPtr<ViewDataWrap> viewDataWrap, bool needsRecordData)
1099 {
1100 if (pattern_) {
1101 pattern_->DumpViewDataPageNode(viewDataWrap, needsRecordData);
1102 }
1103 }
1104
CheckAutoSave()1105 bool FrameNode::CheckAutoSave()
1106 {
1107 if (pattern_) {
1108 return pattern_->CheckAutoSave();
1109 }
1110 return false;
1111 }
1112
MouseToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1113 void FrameNode::MouseToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1114 {
1115 std::string hoverEffect = "HoverEffect.Auto";
1116 /* no fixed attr below, just return */
1117 if (filter.IsFastFilter()) {
1118 return;
1119 }
1120 auto inputEventHub = eventHub_ ? eventHub_->GetOrCreateInputEventHub() : nullptr;
1121 if (inputEventHub) {
1122 hoverEffect = inputEventHub->GetHoverEffectStr();
1123 }
1124 json->PutExtAttr("hoverEffect", hoverEffect.c_str(), filter);
1125 }
1126
TouchToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1127 void FrameNode::TouchToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1128 {
1129 bool touchable = true;
1130 bool monopolizeEvents = false;
1131 std::string hitTestMode = "HitTestMode.Default";
1132 /* no fixed attr below, just return */
1133 if (filter.IsFastFilter()) {
1134 return;
1135 }
1136 auto gestureEventHub = eventHub_ ? eventHub_->GetOrCreateGestureEventHub() : nullptr;
1137 std::vector<DimensionRect> responseRegion;
1138 std::vector<DimensionRect> mouseResponseRegion;
1139 if (gestureEventHub) {
1140 touchable = gestureEventHub->GetTouchable();
1141 hitTestMode = GestureEventHub::GetHitTestModeStr(gestureEventHub);
1142 responseRegion = gestureEventHub->GetResponseRegion();
1143 mouseResponseRegion = gestureEventHub->GetMouseResponseRegion();
1144 monopolizeEvents = gestureEventHub->GetMonopolizeEvents();
1145 }
1146 json->PutExtAttr("touchable", touchable, filter);
1147 json->PutExtAttr("hitTestBehavior", hitTestMode.c_str(), filter);
1148 json->PutExtAttr("monopolizeEvents", monopolizeEvents, filter);
1149 auto jsArr = JsonUtil::CreateArray(true);
1150 for (int32_t i = 0; i < static_cast<int32_t>(responseRegion.size()); ++i) {
1151 auto iStr = std::to_string(i);
1152 jsArr->Put(iStr.c_str(), responseRegion[i].ToJsonString().c_str());
1153 }
1154 json->PutExtAttr("responseRegion", jsArr, filter);
1155 for (int32_t i = 0; i < static_cast<int32_t>(mouseResponseRegion.size()); ++i) {
1156 auto iStr = std::to_string(i);
1157 jsArr->Put(iStr.c_str(), mouseResponseRegion[i].ToJsonString().c_str());
1158 }
1159 json->PutExtAttr("mouseResponseRegion", jsArr, filter);
1160 }
1161
GeometryNodeToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1162 void FrameNode::GeometryNodeToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1163 {
1164 bool hasIdealWidth = false;
1165 bool hasIdealHeight = false;
1166 /* no fixed attr below, just return */
1167 if (filter.IsFastFilter()) {
1168 return;
1169 }
1170 if (layoutProperty_ && layoutProperty_->GetCalcLayoutConstraint()) {
1171 auto selfIdealSize = layoutProperty_->GetCalcLayoutConstraint()->selfIdealSize;
1172 hasIdealWidth = selfIdealSize.has_value() && selfIdealSize.value().Width().has_value();
1173 hasIdealHeight = selfIdealSize.has_value() && selfIdealSize.value().Height().has_value();
1174 }
1175
1176 auto jsonSize = json->GetValue("size");
1177 if (!hasIdealWidth) {
1178 auto idealWidthVpStr = std::to_string(Dimension(geometryNode_->GetFrameSize().Width()).ConvertToVp());
1179 auto widthStr = (idealWidthVpStr.substr(0, idealWidthVpStr.find(".") + SUBSTR_LENGTH) + DIMENSION_UNIT_VP);
1180 json->PutExtAttr("width", widthStr.c_str(), filter);
1181 if (jsonSize) {
1182 jsonSize->Put("width", widthStr.c_str());
1183 }
1184 }
1185
1186 if (!hasIdealHeight) {
1187 auto idealHeightVpStr = std::to_string(Dimension(geometryNode_->GetFrameSize().Height()).ConvertToVp());
1188 auto heightStr = (idealHeightVpStr.substr(0, idealHeightVpStr.find(".") + SUBSTR_LENGTH) + DIMENSION_UNIT_VP);
1189 json->PutExtAttr("height", heightStr.c_str(), filter);
1190 if (jsonSize) {
1191 jsonSize->Put("height", heightStr.c_str());
1192 }
1193 }
1194 }
1195
IsJsCustomPropertyUpdated() const1196 bool FrameNode::IsJsCustomPropertyUpdated() const
1197 {
1198 for (const auto& iter : customPropertyMap_) {
1199 if (!iter.second.empty() && iter.second[1] == "0") {
1200 return false;
1201 }
1202 }
1203 return true;
1204 }
1205
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1206 void FrameNode::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1207 {
1208 if (renderContext_) {
1209 renderContext_->ToJsonValue(json, filter);
1210 }
1211 // scrollable in AccessibilityProperty
1212 ACE_PROPERTY_TO_JSON_VALUE(accessibilityProperty_, AccessibilityProperty);
1213 ACE_PROPERTY_TO_JSON_VALUE(layoutProperty_, LayoutProperty);
1214 ACE_PROPERTY_TO_JSON_VALUE(paintProperty_, PaintProperty);
1215 ACE_PROPERTY_TO_JSON_VALUE(pattern_, Pattern);
1216 if (eventHub_) {
1217 eventHub_->ToJsonValue(json, filter);
1218 }
1219 FocusHub::ToJsonValue(GetFocusHub(), json, filter);
1220 MouseToJsonValue(json, filter);
1221 TouchToJsonValue(json, filter);
1222 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1223 #if defined(PREVIEW)
1224 GeometryNodeToJsonValue(json, filter);
1225 #endif
1226 } else {
1227 GeometryNodeToJsonValue(json, filter);
1228 }
1229 json->PutFixedAttr("id", propInspectorId_.value_or("").c_str(), filter, FIXED_ATTR_ID);
1230 json->Put("isLayoutDirtyMarked", isLayoutDirtyMarked_);
1231 json->Put("isRenderDirtyMarked", isRenderDirtyMarked_);
1232 json->Put("isMeasureBoundary", isMeasureBoundary_);
1233 json->Put("hasPendingRequest", hasPendingRequest_);
1234 json->Put("isFirstBuilding", isFirstBuilding_);
1235 ExtraCustomPropertyToJsonValue(json, filter);
1236 if (IsCNode() || !IsJsCustomPropertyUpdated()) {
1237 auto jsonNode = JsonUtil::Create(true);
1238 for (const auto &iter : customPropertyMap_) {
1239 jsonNode->Put(iter.first.c_str(), iter.second[0].c_str());
1240 }
1241 if (!customPropertyMap_.empty()) {
1242 json->Put("customProperty", jsonNode->ToString().c_str());
1243 }
1244 } else if (getCustomPropertyMapFunc_) {
1245 json->Put("customProperty", getCustomPropertyMapFunc_().c_str());
1246 }
1247 }
1248
ToTreeJson(std::unique_ptr<JsonValue> & json,const InspectorConfig & config) const1249 void FrameNode::ToTreeJson(std::unique_ptr<JsonValue>& json, const InspectorConfig& config) const
1250 {
1251 if (layoutProperty_) {
1252 layoutProperty_->ToTreeJson(json, config);
1253 } else {
1254 LayoutProperty lp;
1255 lp.ToTreeJson(json, config);
1256 }
1257 if (paintProperty_) {
1258 paintProperty_->ToTreeJson(json, config);
1259 }
1260 if (pattern_) {
1261 pattern_->ToTreeJson(json, config);
1262 }
1263 auto id = propInspectorId_.value_or("");
1264 if (!id.empty()) {
1265 json->Put(TreeKey::ID, id.c_str());
1266 }
1267 if (!config.contentOnly && config.callingOnMain) {
1268 auto eventHub = eventHub_ ? eventHub_->GetOrCreateGestureEventHub() : nullptr;
1269 if (eventHub) {
1270 json->Put(TreeKey::CLICKABLE, eventHub->IsAccessibilityClickable());
1271 json->Put(TreeKey::LONG_CLICKABLE, eventHub->IsAccessibilityLongClickable());
1272 }
1273 if (renderContext_) {
1274 json->Put("opacity", renderContext_->GetOpacityValue(1.0));
1275 }
1276 }
1277 json->Put("accessilityId", accessibilityId_);
1278 if (accessibilityProperty_) {
1279 if (!accessibilityProperty_->GetAccessibilityText().empty()) {
1280 json->Put("accessilityContent", accessibilityProperty_->GetAccessibilityText().c_str());
1281 }
1282 if (!accessibilityProperty_->GetAccessibilityDescription().empty()) {
1283 json->Put("accessilityDescription", accessibilityProperty_->GetAccessibilityDescription().c_str());
1284 }
1285 if (!config.contentOnly) {
1286 json->Put(TreeKey::SCROLLABLE, accessibilityProperty_->IsScrollable());
1287 }
1288 }
1289 }
1290
FromJson(const std::unique_ptr<JsonValue> & json)1291 void FrameNode::FromJson(const std::unique_ptr<JsonValue>& json)
1292 {
1293 if (renderContext_) {
1294 renderContext_->FromJson(json);
1295 }
1296 accessibilityProperty_->FromJson(json);
1297 layoutProperty_->FromJson(json);
1298 paintProperty_->FromJson(json);
1299 pattern_->FromJson(json);
1300 if (eventHub_) {
1301 eventHub_->FromJson(json);
1302 }
1303 }
1304
UpdateGeometryTransition()1305 void FrameNode::UpdateGeometryTransition()
1306 {
1307 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
1308 if (geometryTransition) {
1309 layoutProperty_->UpdateGeometryTransition("");
1310 layoutProperty_->UpdateGeometryTransition(geometryTransition->GetId());
1311 MarkDirtyNode();
1312 }
1313 auto children = GetChildren();
1314 for (const auto& child : children) {
1315 child->UpdateGeometryTransition();
1316 }
1317 }
1318
TriggerRsProfilerNodeMountCallbackIfExist()1319 void FrameNode::TriggerRsProfilerNodeMountCallbackIfExist()
1320 {
1321 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
1322 CHECK_NULL_VOID(renderContext_);
1323 auto callback = LayoutInspector::GetRsProfilerNodeMountCallback();
1324 if (callback) {
1325 auto parent = GetParent();
1326 int32_t parentId = -1;
1327 if (parent != nullptr) {
1328 parentId = parent->GetId();
1329 }
1330 FrameNodeInfo info { renderContext_->GetNodeId(), nodeId_, tag_, GetDebugLine(), parentId };
1331 callback(info);
1332 }
1333 #endif
1334 }
1335
OnAttachToMainTree(bool recursive)1336 void FrameNode::OnAttachToMainTree(bool recursive)
1337 {
1338 TriggerRsProfilerNodeMountCallbackIfExist();
1339 if (eventHub_) {
1340 eventHub_->FireOnAttach();
1341 eventHub_->FireOnAppear();
1342 eventHub_->FireEnabledTask();
1343 }
1344 renderContext_->OnNodeAppear(recursive);
1345 pattern_->OnAttachToMainTree();
1346 ClearCachedGlobalOffset();
1347 ClearCachedIsFrameDisappear();
1348
1349 if (isActive_ && SystemProperties::GetDeveloperModeOn()) {
1350 PaintDebugBoundary(SystemProperties::GetDebugBoundaryEnabled());
1351 }
1352 bool forceMeasure = !GetPattern()->ReusedNodeSkipMeasure();
1353 // node may have been measured before AttachToMainTree
1354 if (geometryNode_->GetParentLayoutConstraint().has_value() && !UseOffscreenProcess() && forceMeasure) {
1355 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE_SELF);
1356 }
1357 UINode::OnAttachToMainTree(recursive);
1358 auto context = GetContext();
1359 CHECK_NULL_VOID(context);
1360 auto predictLayoutNode = std::move(predictLayoutNode_);
1361 for (auto& node : predictLayoutNode) {
1362 auto frameNode = node.Upgrade();
1363 if (frameNode && frameNode->isLayoutDirtyMarked_) {
1364 context->AddDirtyLayoutNode(frameNode);
1365 }
1366 }
1367
1368 if (isPropertyDiffMarked_) {
1369 context->AddDirtyPropertyNode(Claim(this));
1370 }
1371 if (!hasPendingRequest_) {
1372 return;
1373 }
1374 context->RequestFrame();
1375 hasPendingRequest_ = false;
1376 }
1377
OnAttachToBuilderNode(NodeStatus nodeStatus)1378 void FrameNode::OnAttachToBuilderNode(NodeStatus nodeStatus)
1379 {
1380 pattern_->OnAttachToBuilderNode(nodeStatus);
1381 }
1382
RenderCustomChild(int64_t deadline)1383 bool FrameNode::RenderCustomChild(int64_t deadline)
1384 {
1385 if (!pattern_->RenderCustomChild(deadline)) {
1386 return false;
1387 }
1388 return UINode::RenderCustomChild(deadline);
1389 }
1390
NotifyColorModeChange(uint32_t colorMode)1391 void FrameNode::NotifyColorModeChange(uint32_t colorMode)
1392 {
1393 FireColorNDKCallback();
1394
1395 if (GetLocalColorMode() != ColorMode::COLOR_MODE_UNDEFINED) {
1396 UINode::NotifyColorModeChange(colorMode);
1397 return;
1398 }
1399
1400 auto parentNode = AceType::DynamicCast<FrameNode>(GetParent());
1401 bool parentRerender = parentNode ? parentNode->GetRerenderable() : GetRerenderable();
1402 // bool parentActive = parentNode ? parentNode->IsActive() : true;
1403 SetRerenderable(parentRerender && ((IsVisible() && IsActive()) || CheckMeasureAnyway()));
1404
1405 if (GetRerenderable() && GetContext()) {
1406 SetDarkMode(GetContext()->GetColorMode() == ColorMode::DARK);
1407 }
1408
1409 if (pattern_) {
1410 pattern_->OnThemeScopeUpdate(GetThemeScopeId());
1411 pattern_->OnColorConfigurationUpdate();
1412 pattern_->OnColorModeChange(colorMode);
1413 }
1414
1415 auto frameNode = AceType::DynamicCast<FrameNode>(this);
1416 if (frameNode && frameNode->GetOverlayNode()) {
1417 frameNode->GetOverlayNode()->NotifyColorModeChange(colorMode);
1418 }
1419
1420 UINode::NotifyColorModeChange(colorMode);
1421 }
1422
OnConfigurationUpdate(const ConfigurationChange & configurationChange)1423 void FrameNode::OnConfigurationUpdate(const ConfigurationChange& configurationChange)
1424 {
1425 if (configurationUpdateCallback_) {
1426 auto cb = configurationUpdateCallback_;
1427 cb(configurationChange);
1428 }
1429 if (configurationChange.languageUpdate) {
1430 pattern_->OnLanguageConfigurationUpdate();
1431 MarkModifyDone();
1432 MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1433 }
1434 if (configurationChange.colorModeUpdate) {
1435 pattern_->OnColorConfigurationUpdate();
1436 if (colorModeUpdateCallback_) {
1437 // copy it first in case of changing colorModeUpdateCallback_ in the callback
1438 auto cb = colorModeUpdateCallback_;
1439 cb();
1440 }
1441 FireColorNDKCallback();
1442 MarkModifyDone();
1443 MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1444 }
1445 if (configurationChange.directionUpdate) {
1446 pattern_->OnDirectionConfigurationUpdate();
1447 MarkModifyDone();
1448 MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1449 }
1450 if (configurationChange.dpiUpdate) {
1451 pattern_->OnDpiConfigurationUpdate();
1452 MarkModifyDone();
1453 MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1454 }
1455 if (configurationChange.fontUpdate) {
1456 pattern_->OnFontConfigurationUpdate();
1457 MarkModifyDone();
1458 MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1459 }
1460 if (configurationChange.iconUpdate) {
1461 pattern_->OnIconConfigurationUpdate();
1462 MarkModifyDone();
1463 MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1464 }
1465 if (configurationChange.skinUpdate) {
1466 MarkModifyDone();
1467 MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1468 }
1469 if (configurationChange.fontScaleUpdate) {
1470 pattern_->OnFontScaleConfigurationUpdate();
1471 MarkModifyDone();
1472 MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1473 }
1474 FireFontNDKCallback(configurationChange);
1475 OnPropertyChangeMeasure();
1476 }
1477
OnPropertyChangeMeasure() const1478 void FrameNode::OnPropertyChangeMeasure() const
1479 {
1480 auto layoutProperty = GetLayoutProperty();
1481 CHECK_NULL_VOID(layoutProperty);
1482 layoutProperty->OnPropertyChangeMeasure();
1483 }
1484
MarkDirtyWithOnProChange(PropertyChangeFlag extraFlag)1485 void FrameNode::MarkDirtyWithOnProChange(PropertyChangeFlag extraFlag)
1486 {
1487 MarkDirtyNode(extraFlag);
1488 auto layoutProperty = GetLayoutProperty();
1489 CHECK_NULL_VOID(layoutProperty);
1490 layoutProperty->OnPropertyChangeMeasure();
1491 }
1492
FireColorNDKCallback()1493 void FrameNode::FireColorNDKCallback()
1494 {
1495 std::shared_lock<std::shared_mutex> lock(colorModeCallbackMutex_);
1496 if (ndkColorModeUpdateCallback_) {
1497 auto colorModeChange = ndkColorModeUpdateCallback_;
1498 auto context = GetContext();
1499 CHECK_NULL_VOID(context);
1500 colorModeChange(context->GetColorMode() == ColorMode::DARK);
1501 }
1502 }
1503
SetNDKColorModeUpdateCallback(const std::function<void (int32_t)> && callback)1504 void FrameNode::SetNDKColorModeUpdateCallback(const std::function<void(int32_t)>&& callback)
1505 {
1506 std::unique_lock<std::shared_mutex> lock(colorModeCallbackMutex_);
1507 ndkColorModeUpdateCallback_ = callback;
1508 auto context = GetContext();
1509 CHECK_NULL_VOID(context);
1510 colorMode_ = context->GetColorMode();
1511 }
1512
FireFontNDKCallback(const ConfigurationChange & configurationChange)1513 void FrameNode::FireFontNDKCallback(const ConfigurationChange& configurationChange)
1514 {
1515 std::shared_lock<std::shared_mutex> lock(fontSizeCallbackMutex_);
1516 if ((configurationChange.fontScaleUpdate || configurationChange.fontWeightScaleUpdate) && ndkFontUpdateCallback_) {
1517 auto fontChangeCallback = ndkFontUpdateCallback_;
1518 auto pipeline = GetContextWithCheck();
1519 CHECK_NULL_VOID(pipeline);
1520 fontChangeCallback(pipeline->GetFontScale(), pipeline->GetFontWeightScale());
1521 }
1522 }
1523
NotifyVisibleChange(VisibleType preVisibility,VisibleType currentVisibility)1524 void FrameNode::NotifyVisibleChange(VisibleType preVisibility, VisibleType currentVisibility)
1525 {
1526 if ((preVisibility != currentVisibility &&
1527 (preVisibility == VisibleType::GONE || currentVisibility == VisibleType::GONE)) &&
1528 SelfExpansive()) {
1529 MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1530 }
1531 pattern_->OnVisibleChange(currentVisibility == VisibleType::VISIBLE);
1532 UpdateChildrenVisible(preVisibility, currentVisibility);
1533 auto pipeline = GetContext();
1534 CHECK_NULL_VOID(pipeline);
1535 auto colorMode = pipeline->GetColorMode() == ColorMode::DARK ? 1 : 0;
1536 if (SystemProperties::ConfigChangePerform() && (colorMode != CheckIsDarkMode())) {
1537 auto parentNode = AceType::DynamicCast<FrameNode>(GetParent());
1538 if (parentNode && parentNode->GetRerenderable()) {
1539 pipeline->SetIsSystemColorChange(false);
1540 SetRerenderable(true);
1541 NotifyColorModeChange(colorMode);
1542 }
1543 }
1544 }
1545
TryVisibleChangeOnDescendant(VisibleType preVisibility,VisibleType currentVisibility)1546 void FrameNode::TryVisibleChangeOnDescendant(VisibleType preVisibility, VisibleType currentVisibility)
1547 {
1548 auto layoutProperty = GetLayoutProperty();
1549 if (layoutProperty && layoutProperty->GetVisibilityValue(VisibleType::VISIBLE) != VisibleType::VISIBLE) {
1550 return;
1551 }
1552 NotifyVisibleChange(preVisibility, currentVisibility);
1553 }
1554
OnDetachFromMainTree(bool recursive,PipelineContext * context)1555 void FrameNode::OnDetachFromMainTree(bool recursive, PipelineContext* context)
1556 {
1557 for (auto [_, callback] : removeToolbarItemCallbacks_) {
1558 if (callback) {
1559 callback();
1560 }
1561 }
1562 auto focusHub = GetFocusHub();
1563 if (focusHub) {
1564 auto focusView = focusHub->GetFirstChildFocusView();
1565 if (focusView) {
1566 focusView->FocusViewClose(true);
1567 }
1568 focusHub->RemoveSelf();
1569 }
1570 pattern_->OnDetachFromMainTree();
1571 if (eventHub_) {
1572 eventHub_->OnDetachClear();
1573 }
1574 CHECK_NULL_VOID(renderContext_);
1575 renderContext_->OnNodeDisappear(recursive);
1576 if (context) {
1577 const auto& safeAreaManager = context->GetSafeAreaManager();
1578 if (safeAreaManager) {
1579 safeAreaManager->RemoveRestoreNode(WeakClaim(this));
1580 }
1581 }
1582 auto accessibilityProperty = GetAccessibilityProperty<AccessibilityProperty>();
1583 CHECK_NULL_VOID(accessibilityProperty);
1584 accessibilityProperty->OnAccessibilityDetachFromMainTree();
1585 }
1586
SwapDirtyLayoutWrapperOnMainThread(const RefPtr<LayoutWrapper> & dirty)1587 void FrameNode::SwapDirtyLayoutWrapperOnMainThread(const RefPtr<LayoutWrapper>& dirty)
1588 {
1589 CHECK_NULL_VOID(dirty);
1590
1591 // update new layout constrain.
1592 layoutProperty_->UpdateLayoutConstraint(dirty->GetLayoutProperty());
1593
1594 // active change flag judge.
1595 SetActive(dirty->IsActive());
1596 if (!isActive_) {
1597 return;
1598 }
1599
1600 // update layout size.
1601 bool frameSizeChange = geometryNode_->GetFrameSize() != dirty->GetGeometryNode()->GetFrameSize();
1602 bool frameOffsetChange = geometryNode_->GetFrameOffset() != dirty->GetGeometryNode()->GetFrameOffset();
1603 bool contentSizeChange = geometryNode_->GetContentSize() != dirty->GetGeometryNode()->GetContentSize();
1604 bool contentOffsetChange = geometryNode_->GetContentOffset() != dirty->GetGeometryNode()->GetContentOffset();
1605
1606 SetGeometryNode(dirty->GetGeometryNode());
1607
1608 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
1609 if (geometryTransition != nullptr && geometryTransition->IsRunning(WeakClaim(this))) {
1610 geometryTransition->DidLayout(dirty);
1611 if (geometryTransition->IsNodeOutAndActive(WeakClaim(this))) {
1612 isLayoutDirtyMarked_ = true;
1613 }
1614 } else if (frameSizeChange || frameOffsetChange || HasPositionProp() ||
1615 (pattern_->GetContextParam().has_value() && contentSizeChange)) {
1616 renderContext_->SyncGeometryProperties(RawPtr(dirty->GetGeometryNode()));
1617 }
1618
1619 // clean layout flag.
1620 layoutProperty_->CleanDirty();
1621 DirtySwapConfig config { frameSizeChange, frameOffsetChange, contentSizeChange, contentOffsetChange };
1622 // check if need to paint content.
1623 auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
1624 CHECK_NULL_VOID(layoutAlgorithmWrapper);
1625 config.skipMeasure = layoutAlgorithmWrapper->SkipMeasure() || dirty->SkipMeasureContent();
1626 config.skipLayout = layoutAlgorithmWrapper->SkipLayout();
1627 if ((config.skipMeasure == false) && (config.skipLayout == false)) {
1628 auto pipeline = GetContext();
1629 CHECK_NULL_VOID(pipeline);
1630 if (eventHub_) {
1631 eventHub_->FireLayoutNDKCallback(pipeline);
1632 }
1633 if (GetInspectorId().has_value()) {
1634 pipeline->OnLayoutCompleted(GetInspectorId()->c_str());
1635 }
1636 }
1637 auto needRerender = pattern_->OnDirtyLayoutWrapperSwap(dirty, config);
1638 needRerender = needRerender || pattern_->OnDirtyLayoutWrapperSwap(dirty, config.skipMeasure, config.skipLayout);
1639 if (needRerender || CheckNeedRender(paintProperty_->GetPropertyChangeFlag())) {
1640 MarkDirtyNode(true, true, PROPERTY_UPDATE_RENDER);
1641 }
1642
1643 // update border.
1644 if (layoutProperty_->GetBorderWidthProperty()) {
1645 if (!renderContext_->HasBorderColor()) {
1646 BorderColorProperty borderColorProperty;
1647 borderColorProperty.SetColor(Color::BLACK);
1648 renderContext_->UpdateBorderColor(borderColorProperty);
1649 }
1650 if (!renderContext_->HasBorderStyle()) {
1651 BorderStyleProperty borderStyleProperty;
1652 borderStyleProperty.SetBorderStyle(BorderStyle::SOLID);
1653 renderContext_->UpdateBorderStyle(borderStyleProperty);
1654 }
1655 if (!renderContext_->HasDashGap()) {
1656 BorderWidthProperty dashGapProperty;
1657 dashGapProperty.SetBorderWidth(Dimension(-1));
1658 renderContext_->UpdateDashGap(dashGapProperty);
1659 }
1660 if (!renderContext_->HasDashWidth()) {
1661 BorderWidthProperty dashWidthProperty;
1662 dashWidthProperty.SetBorderWidth(Dimension(-1));
1663 renderContext_->UpdateDashWidth(dashWidthProperty);
1664 }
1665 if (layoutProperty_->GetLayoutConstraint().has_value()) {
1666 renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
1667 ScaleProperty::CreateScaleProperty(),
1668 layoutProperty_->GetLayoutConstraint()->percentReference.Width()));
1669 } else {
1670 renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
1671 ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth()));
1672 }
1673 }
1674
1675 UpdateBackground();
1676
1677 // update focus state
1678 auto focusHub = GetFocusHub();
1679 if (focusHub && focusHub->IsCurrentFocus()) {
1680 focusHub->ClearFocusState(false);
1681 focusHub->PaintFocusState(false);
1682 }
1683
1684 // rebuild child render node.
1685 RebuildRenderContextTree();
1686 }
1687
SetMeasureCallback(const std::function<void (RefPtr<Kit::FrameNode>)> & measureCallback)1688 void FrameNode::SetMeasureCallback(const std::function<void(RefPtr<Kit::FrameNode>)>& measureCallback)
1689 {
1690 measureCallback_ = std::move(measureCallback);
1691 }
1692
SetBackgroundLayoutConstraint(const RefPtr<FrameNode> & customNode)1693 void FrameNode::SetBackgroundLayoutConstraint(const RefPtr<FrameNode>& customNode)
1694 {
1695 CHECK_NULL_VOID(customNode);
1696 LayoutConstraintF layoutConstraint;
1697 layoutConstraint.scaleProperty = ScaleProperty::CreateScaleProperty();
1698 auto backgroundRect = GetBackGroundAccumulatedSafeAreaExpand();
1699 layoutConstraint.percentReference.SetWidth(backgroundRect.Width());
1700 layoutConstraint.percentReference.SetHeight(backgroundRect.Height());
1701 layoutConstraint.maxSize.SetWidth(backgroundRect.Width());
1702 layoutConstraint.maxSize.SetHeight(backgroundRect.Height());
1703 customNode->GetGeometryNode()->SetParentLayoutConstraint(layoutConstraint);
1704 }
1705
AdjustGridOffset()1706 void FrameNode::AdjustGridOffset()
1707 {
1708 if (!isActive_) {
1709 return;
1710 }
1711 if (layoutProperty_->UpdateGridOffset(Claim(this))) {
1712 renderContext_->SyncGeometryProperties(RawPtr(GetGeometryNode()));
1713 }
1714 }
1715
ClearUserOnAreaChange()1716 void FrameNode::ClearUserOnAreaChange()
1717 {
1718 if (eventHub_) {
1719 eventHub_->ClearUserOnAreaChanged();
1720 }
1721 }
1722
SetOnAreaChangeCallback(OnAreaChangedFunc && callback)1723 void FrameNode::SetOnAreaChangeCallback(OnAreaChangedFunc&& callback)
1724 {
1725 InitLastArea();
1726 CreateEventHubInner();
1727 CHECK_NULL_VOID(eventHub_);
1728 eventHub_->SetOnAreaChanged(std::move(callback));
1729 }
1730
TriggerOnAreaChangeCallback(uint64_t nanoTimestamp,int32_t areaChangeMinDepth)1731 void FrameNode::TriggerOnAreaChangeCallback(uint64_t nanoTimestamp, int32_t areaChangeMinDepth)
1732 {
1733 if (!IsActive()) {
1734 if (IsDebugInspectorId()) {
1735 TAG_LOGD(AceLogTag::ACE_UIEVENT, "OnAreaChange Node(%{public}s/%{public}d) is inActive", tag_.c_str(),
1736 nodeId_);
1737 }
1738 return;
1739 }
1740 #ifdef WINDOW_SCENE_SUPPORTED
1741 auto container = Container::Current();
1742 if (container && container->IsDynamicRender() &&
1743 container->GetUIContentType() == UIContentType::DYNAMIC_COMPONENT) {
1744 DynamicComponentManager::TriggerOnAreaChangeCallback(this, nanoTimestamp);
1745 return;
1746 }
1747 #endif
1748 if (eventHub_ && (eventHub_->HasOnAreaChanged() || eventHub_->HasInnerOnAreaChanged()) && lastFrameRect_ &&
1749 lastParentOffsetToWindow_) {
1750 auto currFrameRect = GetFrameRectWithSafeArea();
1751 if (renderContext_ && renderContext_->GetPositionProperty()) {
1752 if (renderContext_->GetPositionProperty()->HasPosition()) {
1753 auto renderPosition = ContextPositionConvertToPX(
1754 renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
1755 currFrameRect.SetOffset(
1756 { static_cast<float>(renderPosition.first), static_cast<float>(renderPosition.second) });
1757 }
1758 }
1759 bool logFlag = IsDebugInspectorId();
1760 auto currParentOffsetToWindow =
1761 CalculateOffsetRelativeToWindow(nanoTimestamp, logFlag, areaChangeMinDepth) - currFrameRect.GetOffset();
1762 if (logFlag) {
1763 TAG_LOGD(AceLogTag::ACE_UIEVENT,
1764 "OnAreaChange Node(%{public}s/%{public}d) rect:%{public}s lastRect:%{public}s "
1765 "parentRectToWindow:%{public}s lastParentRectToWindow:%{public}s",
1766 tag_.c_str(), nodeId_, currFrameRect.ToString().c_str(), (*lastFrameRect_).ToString().c_str(),
1767 currParentOffsetToWindow.ToString().c_str(), (*lastParentOffsetToWindow_).ToString().c_str());
1768 TAG_LOGD(AceLogTag::ACE_UIEVENT, "OnAreaChange End of calculation %{public}s",
1769 currFrameRect != *lastFrameRect_ || currParentOffsetToWindow != *lastParentOffsetToWindow_
1770 ? "non-execution"
1771 : "execution");
1772 }
1773 eventHub_->HandleOnAreaChange(
1774 lastFrameRect_, lastParentOffsetToWindow_, currFrameRect, currParentOffsetToWindow);
1775 } else {
1776 // if in this branch, next time cache is not trusted
1777 ClearCachedGlobalOffset();
1778 }
1779 pattern_->OnAreaChangedInner();
1780 }
1781
SetOnSizeChangeCallback(OnSizeChangedFunc && callback)1782 void FrameNode::SetOnSizeChangeCallback(OnSizeChangedFunc&& callback)
1783 {
1784 if (!lastFrameNodeRect_) {
1785 lastFrameNodeRect_ = std::make_unique<RectF>();
1786 }
1787 CreateEventHubInner();
1788 CHECK_NULL_VOID(eventHub_);
1789 eventHub_->SetOnSizeChanged(std::move(callback));
1790 }
1791
AddInnerOnSizeChangeCallback(int32_t id,OnSizeChangedFunc && callback)1792 void FrameNode::AddInnerOnSizeChangeCallback(int32_t id, OnSizeChangedFunc&& callback)
1793 {
1794 if (!lastFrameNodeRect_) {
1795 lastFrameNodeRect_ = std::make_unique<RectF>();
1796 }
1797 CreateEventHubInner();
1798 CHECK_NULL_VOID(eventHub_);
1799 eventHub_->AddInnerOnSizeChanged(id, std::move(callback));
1800 }
1801
SetJSFrameNodeOnSizeChangeCallback(OnSizeChangedFunc && callback)1802 void FrameNode::SetJSFrameNodeOnSizeChangeCallback(OnSizeChangedFunc&& callback)
1803 {
1804 if (!lastFrameNodeRect_) {
1805 lastFrameNodeRect_ = std::make_unique<RectF>();
1806 }
1807 CreateEventHubInner();
1808 CHECK_NULL_VOID(eventHub_);
1809 eventHub_->SetJSFrameNodeOnSizeChangeCallback(std::move(callback));
1810 }
1811
GetRectWithRender()1812 RectF FrameNode::GetRectWithRender()
1813 {
1814 RectF currFrameRect;
1815 if (renderContext_) {
1816 currFrameRect = renderContext_->GetPaintRectWithoutTransform();
1817 }
1818 if (renderContext_ && renderContext_->GetPositionProperty()) {
1819 if (renderContext_->GetPositionProperty()->HasPosition()) {
1820 auto renderPosition =
1821 ContextPositionConvertToPX(renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
1822 currFrameRect.SetOffset(
1823 { static_cast<float>(renderPosition.first), static_cast<float>(renderPosition.second) });
1824 }
1825 }
1826 return currFrameRect;
1827 }
1828
CheckAncestorPageShow()1829 bool FrameNode::CheckAncestorPageShow()
1830 {
1831 auto pageNode = GetPageNode();
1832 if (!pageNode) {
1833 return true;
1834 }
1835 return pageNode->GetPattern<PagePattern>()->IsOnShow();
1836 }
1837
TriggerOnSizeChangeCallback()1838 void FrameNode::TriggerOnSizeChangeCallback()
1839 {
1840 if (!IsActive() || !CheckAncestorPageShow()) {
1841 return;
1842 }
1843 if (eventHub_ && (eventHub_->HasOnSizeChanged() || eventHub_->HasInnerOnSizeChanged()) && lastFrameNodeRect_) {
1844 auto currFrameRect = GetRectWithRender();
1845 if (currFrameRect.GetSize() != (*lastFrameNodeRect_).GetSize()) {
1846 onSizeChangeDumpInfo dumpInfo { GetCurrentTimestamp(), *lastFrameNodeRect_, currFrameRect };
1847 if (onSizeChangeDumpInfos.size() >= SIZE_CHANGE_DUMP_SIZE) {
1848 onSizeChangeDumpInfos.erase(onSizeChangeDumpInfos.begin());
1849 }
1850 onSizeChangeDumpInfos.emplace_back(dumpInfo);
1851 if (eventHub_->HasOnSizeChanged()) {
1852 eventHub_->FireOnSizeChanged(*lastFrameNodeRect_, currFrameRect);
1853 }
1854 if (eventHub_->HasInnerOnSizeChanged()) {
1855 eventHub_->FireInnerOnSizeChanged(*lastFrameNodeRect_, currFrameRect);
1856 }
1857 eventHub_->FireJSFrameNodeOnSizeChanged(*lastFrameNodeRect_, currFrameRect);
1858 if (lastFrameNodeRect_) {
1859 *lastFrameNodeRect_ = currFrameRect;
1860 }
1861 }
1862 }
1863 }
1864
IsFrameDisappear() const1865 bool FrameNode::IsFrameDisappear() const
1866 {
1867 auto context = GetContext();
1868 CHECK_NULL_RETURN(context, true);
1869 bool isFrameDisappear = !context->GetOnShow() || !IsOnMainTree() || !IsVisible();
1870 if (isFrameDisappear) {
1871 return true;
1872 }
1873 bool curFrameIsActive = isActive_;
1874 bool curIsVisible = IsVisible();
1875 auto parent = GetParent();
1876 while (parent) {
1877 auto parentFrame = AceType::DynamicCast<FrameNode>(parent);
1878 if (!parentFrame) {
1879 parent = parent->GetParent();
1880 continue;
1881 }
1882 if (!parentFrame->isActive_) {
1883 curFrameIsActive = false;
1884 break;
1885 }
1886 if (!parentFrame->IsVisible()) {
1887 curIsVisible = false;
1888 break;
1889 }
1890 parent = parent->GetParent();
1891 }
1892 return !curIsVisible || !curFrameIsActive;
1893 }
1894
IsFrameDisappear(uint64_t timestamp,int32_t isVisibleChangeMinDepth)1895 bool FrameNode::IsFrameDisappear(uint64_t timestamp, int32_t isVisibleChangeMinDepth)
1896 {
1897 auto context = GetContext();
1898 CHECK_NULL_RETURN(context, true);
1899 auto isOnShow = context->GetOnShow();
1900 auto isOnMainTree = AllowVisibleAreaCheck();
1901 auto isSelfVisible = IsVisible();
1902 if (!isSelfVisible) {
1903 SetVisibleAreaChangeTriggerReason(VisibleAreaChangeTriggerReason::SELF_INVISIBLE);
1904 }
1905 if (!isOnMainTree) {
1906 SetVisibleAreaChangeTriggerReason(VisibleAreaChangeTriggerReason::IS_NOT_ON_MAINTREE);
1907 }
1908 if (!isOnShow) {
1909 SetVisibleAreaChangeTriggerReason(VisibleAreaChangeTriggerReason::BACKGROUND);
1910 }
1911 bool isFrameDisappear = !isOnShow || !isOnMainTree || !isSelfVisible;
1912 if (isFrameDisappear) {
1913 // if in this branch, next time cache is not trusted
1914 ClearCachedIsFrameDisappear();
1915 return true;
1916 }
1917 auto result = IsFrameAncestorDisappear(timestamp, isVisibleChangeMinDepth);
1918 if (result) {
1919 SetVisibleAreaChangeTriggerReason(VisibleAreaChangeTriggerReason::ANCESTOR_INVISIBLE);
1920 }
1921 return result;
1922 }
1923
IsFrameAncestorDisappear(uint64_t timestamp,int32_t isVisibleChangeMinDepth)1924 bool FrameNode::IsFrameAncestorDisappear(uint64_t timestamp, int32_t isVisibleChangeMinDepth)
1925 {
1926 bool curFrameIsActive = isActive_;
1927 bool curIsVisible = IsVisible();
1928 bool result = !curIsVisible || !curFrameIsActive;
1929 RefPtr<FrameNode> parentUi = GetAncestorNodeOfFrame(false);
1930 if (!parentUi || result) {
1931 // if in this branch, next time cache is not trusted
1932 ClearCachedIsFrameDisappear();
1933 return result;
1934 }
1935
1936 // if this node have not calculate once, then it will calculate to root
1937 isVisibleChangeMinDepth = cachedIsFrameDisappear_.first > 0 ? isVisibleChangeMinDepth : -1;
1938 // MinDepth < 0, it do not work
1939 // MinDepth >= 0, and this node have calculate once
1940 // MinDepth = 0, no change from last frame, use cache directly
1941 // MinDepth > 0, and parent->GetDepth < MinDepth, parent do not change, use cache directly
1942 auto parentIsFrameDisappear = parentUi->cachedIsFrameDisappear_;
1943 if ((parentIsFrameDisappear.first == timestamp) ||
1944 ((isVisibleChangeMinDepth >= 0) && parentIsFrameDisappear.first && (isVisibleChangeMinDepth == 0 ||
1945 ((isVisibleChangeMinDepth > 0) && (parentUi->GetDepth() < isVisibleChangeMinDepth))))) {
1946 result = result || parentIsFrameDisappear.second;
1947 cachedIsFrameDisappear_ = { timestamp, result };
1948 return result;
1949 }
1950
1951 result = result || parentUi->IsFrameAncestorDisappear(timestamp, isVisibleChangeMinDepth);
1952
1953 cachedIsFrameDisappear_ = { timestamp, result };
1954 return result;
1955 }
1956
TriggerVisibleAreaChangeCallback(uint64_t timestamp,bool forceDisappear,int32_t isVisibleChangeMinDepth)1957 void FrameNode::TriggerVisibleAreaChangeCallback(
1958 uint64_t timestamp, bool forceDisappear, int32_t isVisibleChangeMinDepth)
1959 {
1960 auto context = GetContext();
1961 CHECK_NULL_VOID(context);
1962 CHECK_NULL_VOID(eventHub_);
1963 ProcessThrottledVisibleCallback(forceDisappear);
1964 auto hasInnerCallback = eventHub_->HasVisibleAreaCallback(false);
1965 auto hasUserCallback = eventHub_->HasVisibleAreaCallback(true);
1966 if (!hasInnerCallback && !hasUserCallback) {
1967 ClearCachedIsFrameDisappear();
1968 return;
1969 }
1970 auto& visibleAreaUserRatios = eventHub_->GetVisibleAreaRatios(true);
1971 auto& visibleAreaUserCallback = eventHub_->GetVisibleAreaCallback(true);
1972 auto& visibleAreaInnerRatios = eventHub_->GetVisibleAreaRatios(false);
1973 auto& visibleAreaInnerCallback = eventHub_->GetVisibleAreaCallback(false);
1974 if (forceDisappear || IsFrameDisappear(timestamp, isVisibleChangeMinDepth)) {
1975 if (IsDebugInspectorId()) {
1976 TAG_LOGD(AceLogTag::ACE_UIEVENT, "OnVisibleAreaChange Node(%{public}s/%{public}d) "
1977 "lastRatio(User:%{public}s/Inner:%{public}s) forceDisappear:%{public}d frameDisappear:%{public}d ",
1978 tag_.c_str(), nodeId_, std::to_string(lastVisibleRatio_).c_str(),
1979 std::to_string(lastInnerVisibleRatio_).c_str(), forceDisappear, IsFrameDisappear(timestamp));
1980 }
1981 if (!NearEqual(lastInnerVisibleRatio_, VISIBLE_RATIO_MIN)) {
1982 ProcessAllVisibleCallback(visibleAreaInnerRatios, visibleAreaInnerCallback, VISIBLE_RATIO_MIN,
1983 lastInnerVisibleCallbackRatio_, false, true);
1984 lastInnerVisibleRatio_ = VISIBLE_RATIO_MIN;
1985 }
1986 if (!NearEqual(lastVisibleRatio_, VISIBLE_RATIO_MIN)) {
1987 ProcessAllVisibleCallback(
1988 visibleAreaUserRatios, visibleAreaUserCallback, VISIBLE_RATIO_MIN, lastVisibleCallbackRatio_);
1989 lastVisibleRatio_ = VISIBLE_RATIO_MIN;
1990 }
1991 return;
1992 }
1993 auto visibleResult = GetCacheVisibleRect(timestamp, IsDebugInspectorId());
1994 SetVisibleAreaChangeTriggerReason(VisibleAreaChangeTriggerReason::VISIBLE_AREA_CHANGE);
1995 DispatchVisibleAreaChangeEvent(visibleResult);
1996 }
1997
DispatchVisibleAreaChangeEvent(const CacheVisibleRectResult & visibleResult)1998 void FrameNode::DispatchVisibleAreaChangeEvent(const CacheVisibleRectResult& visibleResult)
1999 {
2000 CHECK_NULL_VOID(eventHub_);
2001 auto hasInnerCallback = eventHub_->HasVisibleAreaCallback(false);
2002 auto hasUserCallback = eventHub_->HasVisibleAreaCallback(true);
2003 auto& visibleAreaUserRatios = eventHub_->GetVisibleAreaRatios(true);
2004 auto& visibleAreaUserCallback = eventHub_->GetVisibleAreaCallback(true);
2005 auto& visibleAreaInnerRatios = eventHub_->GetVisibleAreaRatios(false);
2006 auto& visibleAreaInnerCallback = eventHub_->GetVisibleAreaCallback(false);
2007 if (hasInnerCallback) {
2008 if (isCalculateInnerVisibleRectClip_) {
2009 ProcessVisibleAreaChangeEvent(visibleResult.innerVisibleRect, visibleResult.innerFrameRect,
2010 visibleAreaInnerRatios, visibleAreaInnerCallback, false);
2011 } else {
2012 ProcessVisibleAreaChangeEvent(visibleResult.visibleRect, visibleResult.frameRect, visibleAreaInnerRatios,
2013 visibleAreaInnerCallback, false);
2014 }
2015 }
2016 if (hasUserCallback) {
2017 if (visibleAreaUserCallback.isOutOfBoundsAllowed) {
2018 ProcessVisibleAreaChangeEvent(visibleResult.innerVisibleRect, visibleResult.innerFrameRect,
2019 visibleAreaUserRatios, visibleAreaUserCallback, true);
2020 } else {
2021 ProcessVisibleAreaChangeEvent(visibleResult.visibleRect, visibleResult.frameRect, visibleAreaUserRatios,
2022 visibleAreaUserCallback, true);
2023 }
2024 }
2025 }
2026
ProcessVisibleAreaChangeEvent(const RectF & visibleRect,const RectF & frameRect,const std::vector<double> & visibleAreaRatios,VisibleCallbackInfo & visibleAreaCallback,bool isUser)2027 void FrameNode::ProcessVisibleAreaChangeEvent(const RectF& visibleRect, const RectF& frameRect,
2028 const std::vector<double>& visibleAreaRatios, VisibleCallbackInfo& visibleAreaCallback, bool isUser)
2029 {
2030 double currentVisibleRatio =
2031 std::clamp(CalculateCurrentVisibleRatio(visibleRect, frameRect), VISIBLE_RATIO_MIN, VISIBLE_RATIO_MAX);
2032 if (IsDebugInspectorId()) {
2033 TAG_LOGD(AceLogTag::ACE_UIEVENT,
2034 "OnVisibleAreaChange Node(%{public}s/%{public}d) Ratio(cur:%{public}s/last:%{public}s)", tag_.c_str(),
2035 nodeId_, std::to_string(currentVisibleRatio).c_str(), std::to_string(lastVisibleRatio_).c_str());
2036 TAG_LOGD(AceLogTag::ACE_UIEVENT, "OnVisibleAreaChange End of calculation %{public}s",
2037 NearEqual(currentVisibleRatio, lastVisibleRatio_) ? "non-execution" : "execution");
2038 }
2039 if (isUser) {
2040 if (visibleAreaCallback.isOutOfBoundsAllowed) {
2041 auto rect = renderContext_->GetPaintRectWithoutTransform();
2042 currentVisibleRatio = rect.IsEmpty() ? VISIBLE_RATIO_MIN : currentVisibleRatio;
2043 }
2044 if (!NearEqual(currentVisibleRatio, lastVisibleRatio_)) {
2045 auto lastVisibleCallbackRatio = lastVisibleCallbackRatio_;
2046 ProcessAllVisibleCallback(
2047 visibleAreaRatios, visibleAreaCallback, currentVisibleRatio, lastVisibleCallbackRatio);
2048 lastVisibleRatio_ = currentVisibleRatio;
2049 }
2050 } else {
2051 if (!NearEqual(currentVisibleRatio, lastInnerVisibleRatio_)) {
2052 auto lastVisibleCallbackRatio = lastInnerVisibleCallbackRatio_;
2053 ProcessAllVisibleCallback(visibleAreaRatios, visibleAreaCallback, currentVisibleRatio,
2054 lastVisibleCallbackRatio, false, true);
2055 lastInnerVisibleRatio_ = currentVisibleRatio;
2056 }
2057 }
2058 }
2059
CalculateCurrentVisibleRatio(const RectF & visibleRect,const RectF & renderRect)2060 double FrameNode::CalculateCurrentVisibleRatio(const RectF& visibleRect, const RectF& renderRect)
2061 {
2062 if (visibleRect.IsEmpty() || renderRect.IsEmpty()) {
2063 return 0.0;
2064 }
2065 return visibleRect.Width() * visibleRect.Height() / (renderRect.Width() * renderRect.Height());
2066 }
2067
ProcessAllVisibleCallback(const std::vector<double> & visibleAreaUserRatios,VisibleCallbackInfo & visibleAreaUserCallback,double currentVisibleRatio,double lastVisibleRatio,bool isThrottled,bool isInner)2068 void FrameNode::ProcessAllVisibleCallback(const std::vector<double>& visibleAreaUserRatios,
2069 VisibleCallbackInfo& visibleAreaUserCallback, double currentVisibleRatio, double lastVisibleRatio,
2070 bool isThrottled, bool isInner)
2071 {
2072 bool isHandled = false;
2073 bool isVisible = false;
2074 double* lastVisibleCallbackRatio = isThrottled ? &lastThrottledVisibleCbRatio_ :
2075 (isInner ? &lastInnerVisibleCallbackRatio_ : &lastVisibleCallbackRatio_);
2076
2077 for (const auto& callbackRatio : visibleAreaUserRatios) {
2078 if (GreatNotEqual(currentVisibleRatio, callbackRatio) && LessOrEqual(lastVisibleRatio, callbackRatio)) {
2079 *lastVisibleCallbackRatio = currentVisibleRatio;
2080 isVisible = true;
2081 isHandled = true;
2082 } else if (LessNotEqual(currentVisibleRatio, callbackRatio) && GreatOrEqual(lastVisibleRatio, callbackRatio)) {
2083 *lastVisibleCallbackRatio = currentVisibleRatio;
2084 isVisible = false;
2085 isHandled = true;
2086 } else if (NearEqual(callbackRatio, VISIBLE_RATIO_MIN) && NearEqual(currentVisibleRatio, callbackRatio)) {
2087 *lastVisibleCallbackRatio = VISIBLE_RATIO_MIN;
2088 currentVisibleRatio = VISIBLE_RATIO_MIN;
2089 isVisible = false;
2090 isHandled = true;
2091 } else if (NearEqual(callbackRatio, VISIBLE_RATIO_MAX) && NearEqual(currentVisibleRatio, callbackRatio)) {
2092 *lastVisibleCallbackRatio = VISIBLE_RATIO_MAX;
2093 currentVisibleRatio = VISIBLE_RATIO_MAX;
2094 isVisible = true;
2095 isHandled = true;
2096 }
2097 }
2098
2099 auto callback = visibleAreaUserCallback.callback;
2100 if (isHandled && callback) {
2101 if (tag_ == V2::WEB_ETS_TAG) {
2102 TAG_LOGI(AceLogTag::ACE_UIEVENT, "exp=%{public}d ratio=%{public}s %{public}d-%{public}s reason=%{public}d",
2103 isVisible, std::to_string(currentVisibleRatio).c_str(), nodeId_,
2104 std::to_string(accessibilityId_).c_str(), static_cast<int32_t>(visibleAreaChangeTriggerReason_));
2105 }
2106 callback(isVisible, currentVisibleRatio);
2107 }
2108 }
2109
ThrottledVisibleTask()2110 void FrameNode::ThrottledVisibleTask()
2111 {
2112 CHECK_NULL_VOID(eventHub_);
2113 auto& userRatios = eventHub_->GetThrottledVisibleAreaRatios();
2114 auto& userCallback = eventHub_->GetThrottledVisibleAreaCallback();
2115 if (!userCallback.callback) {
2116 throttledCallbackOnTheWay_ = false;
2117 return;
2118 }
2119 if (!throttledCallbackOnTheWay_) {
2120 return;
2121 }
2122
2123 auto pipeline = GetContext();
2124 CHECK_NULL_VOID(pipeline);
2125 auto visibleResult = GetCacheVisibleRect(pipeline->GetVsyncTime());
2126 RectF frameRect = visibleResult.frameRect;
2127 RectF visibleRect = visibleResult.visibleRect;
2128 double ratio = IsFrameDisappear() ? VISIBLE_RATIO_MIN
2129 : std::clamp(CalculateCurrentVisibleRatio(visibleRect, frameRect),
2130 VISIBLE_RATIO_MIN, VISIBLE_RATIO_MAX);
2131 if (!NearEqual(ratio, lastThrottledVisibleRatio_)) {
2132 ProcessAllVisibleCallback(userRatios, userCallback, ratio, lastThrottledVisibleCbRatio_, true);
2133 lastThrottledVisibleRatio_ = ratio;
2134 }
2135 throttledCallbackOnTheWay_ = false;
2136 lastThrottledTriggerTime_ = GetCurrentTimestamp();
2137 }
2138
ProcessThrottledVisibleCallback(bool forceDisappear)2139 void FrameNode::ProcessThrottledVisibleCallback(bool forceDisappear)
2140 {
2141 CHECK_NULL_VOID(eventHub_);
2142 auto& visibleAreaUserCallback = eventHub_->GetThrottledVisibleAreaCallback();
2143 CHECK_NULL_VOID(visibleAreaUserCallback.callback);
2144
2145 if (forceDisappear && !NearEqual(lastThrottledVisibleRatio_, VISIBLE_RATIO_MIN)) {
2146 auto& userRatios = eventHub_->GetThrottledVisibleAreaRatios();
2147 ProcessAllVisibleCallback(
2148 userRatios, visibleAreaUserCallback, VISIBLE_RATIO_MIN, lastThrottledVisibleCbRatio_, true);
2149 lastThrottledVisibleRatio_ = VISIBLE_RATIO_MIN;
2150 return;
2151 }
2152
2153 auto task = [weak = WeakClaim(this)]() {
2154 auto node = weak.Upgrade();
2155 CHECK_NULL_VOID(node);
2156 node->ThrottledVisibleTask();
2157 };
2158
2159 auto pipeline = GetContextRefPtr();
2160 CHECK_NULL_VOID(pipeline);
2161 auto executor = pipeline->GetTaskExecutor();
2162 CHECK_NULL_VOID(executor);
2163
2164 if (throttledCallbackOnTheWay_) {
2165 return;
2166 }
2167
2168 throttledCallbackOnTheWay_ = true;
2169 int64_t interval = GetCurrentTimestamp() - lastThrottledTriggerTime_;
2170 if (interval < visibleAreaUserCallback.period) {
2171 executor->PostDelayedTask(std::move(task), TaskExecutor::TaskType::UI, visibleAreaUserCallback.period,
2172 "ThrottledVisibleChangeCallback", PriorityType::IDLE);
2173 } else {
2174 executor->PostTask(
2175 std::move(task), TaskExecutor::TaskType::UI, "ThrottledVisibleChangeCallback", PriorityType::IDLE);
2176 }
2177 }
2178
SetActive(bool active,bool needRebuildRenderContext)2179 void FrameNode::SetActive(bool active, bool needRebuildRenderContext)
2180 {
2181 bool activeChanged = false;
2182 if (active && !isActive_) {
2183 pattern_->OnActive();
2184 isActive_ = true;
2185 activeChanged = true;
2186 }
2187 if (!active && isActive_) {
2188 pattern_->OnInActive();
2189 isActive_ = false;
2190 activeChanged = true;
2191 ClearCachedGlobalOffset();
2192 }
2193 CHECK_NULL_VOID(activeChanged);
2194
2195 auto pipeline = GetContext();
2196 CHECK_NULL_VOID(pipeline);
2197 pipeline->SetIsDisappearChangeNodeMinDepth(GetDepth());
2198 pipeline->SetAreaChangeNodeMinDepth(GetDepth());
2199
2200 auto parent = GetAncestorNodeOfFrame(false);
2201 if (parent) {
2202 if (subtreeIgnoreCount_ != 0 && activeChanged) {
2203 int inc = isActive_ ? subtreeIgnoreCount_ : -subtreeIgnoreCount_;
2204 if (SystemProperties::GetMeasureDebugTraceEnabled()) {
2205 ACE_MEASURE_SCOPED_TRACE(
2206 "UpdateIgnoreCount:SetActive[%s][self:%d] updateCount=%d", tag_.c_str(), nodeId_, inc);
2207 }
2208 parent->UpdateIgnoreCount(inc);
2209 }
2210 parent->MarkNeedSyncRenderTree();
2211 if (needRebuildRenderContext) {
2212 auto pipeline = GetContext();
2213 CHECK_NULL_VOID(pipeline);
2214 auto task = [weak = AceType::WeakClaim(AceType::RawPtr(parent))]() {
2215 auto parent = weak.Upgrade();
2216 CHECK_NULL_VOID(parent);
2217 parent->RebuildRenderContextTree();
2218 };
2219 pipeline->AddAfterLayoutTask(task);
2220 }
2221 }
2222 if (isActive_ && SystemProperties::GetDeveloperModeOn()) {
2223 PaintDebugBoundary(SystemProperties::GetDebugBoundaryEnabled());
2224 }
2225 }
2226
SetGeometryNode(const RefPtr<GeometryNode> & node)2227 void FrameNode::SetGeometryNode(const RefPtr<GeometryNode>& node)
2228 {
2229 if (node == nullptr) {
2230 TAG_LOGW(AceLogTag::ACE_DEFAULT_DOMAIN, "SetGeometryNode failed: tag:%{public}s, id:%{public}d] ",
2231 tag_.c_str(), nodeId_);
2232 }
2233 geometryNode_ = node;
2234 }
2235
SetNodeFreeze(bool isFreeze)2236 void FrameNode::SetNodeFreeze(bool isFreeze)
2237 {
2238 CHECK_NULL_VOID(renderContext_);
2239 if (SystemProperties::IsPageTransitionFreeze()) {
2240 renderContext_->UpdateFreeze(isFreeze);
2241 }
2242 }
2243
CreateLayoutTask(bool forceUseMainThread,LayoutType layoutTaskType)2244 void FrameNode::CreateLayoutTask(bool forceUseMainThread, LayoutType layoutTaskType)
2245 {
2246 if (!isLayoutDirtyMarked_ && (layoutTaskType == LayoutType::NONE)) {
2247 return;
2248 }
2249
2250 auto context = GetContext();
2251 CHECK_NULL_VOID(context);
2252 context->SetAreaChangeNodeMinDepth(GetDepth());
2253
2254 SetRootMeasureNode(true);
2255 UpdateLayoutPropertyFlag();
2256 SetSkipSyncGeometryNode(false);
2257 if (layoutProperty_->GetLayoutRect()) {
2258 SetActive(true, true);
2259 Measure(std::nullopt);
2260 Layout();
2261 } else {
2262 if (layoutTaskType != LayoutType::LAYOUT_FOR_IGNORE) {
2263 auto layoutConstraint = GetLayoutConstraint();
2264 ACE_SCOPED_TRACE_COMMERCIAL("CreateTaskMeasure[%s][self:%d][parent:%d][layoutConstraint:%s]"
2265 "[layoutPriority:%d][pageId:%d][depth:%d]",
2266 tag_.c_str(), nodeId_, GetAncestorNodeOfFrame(false) ? GetAncestorNodeOfFrame(false)->GetId() : 0,
2267 layoutConstraint.ToString().c_str(), layoutPriority_, hostPageId_, depth_);
2268 SetIgnoreLayoutProcess(layoutTaskType == LayoutType::MEASURE_FOR_IGNORE);
2269 Measure(layoutConstraint);
2270 ResetIgnoreLayoutProcess();
2271 } else {
2272 // LayoutTask for postponed layouting on ignoreLayoutSafeArea-container node, which should skip measuring.
2273 }
2274
2275 {
2276 ACE_SCOPED_TRACE_COMMERCIAL("CreateTaskLayout[%s][self:%d][parent:%d][layoutPriority:%d]"
2277 "[pageId:%d][depth:%d]",
2278 tag_.c_str(), nodeId_, GetAncestorNodeOfFrame(false) ? GetAncestorNodeOfFrame(false)->GetId() : 0,
2279 layoutPriority_, hostPageId_, depth_);
2280 SetIgnoreLayoutProcess(layoutTaskType == LayoutType::LAYOUT_FOR_IGNORE);
2281 Layout();
2282 ResetIgnoreLayoutProcess();
2283 }
2284 }
2285 SetRootMeasureNode(false);
2286 }
2287
CreateRenderTask(bool forceUseMainThread)2288 std::optional<UITask> FrameNode::CreateRenderTask(bool forceUseMainThread)
2289 {
2290 if (!isRenderDirtyMarked_) {
2291 return std::nullopt;
2292 }
2293 auto wrapper = CreatePaintWrapper();
2294 CHECK_NULL_RETURN(wrapper, std::nullopt);
2295 auto task = [weak = WeakClaim(this), wrapper, paintProperty = paintProperty_]() {
2296 auto self = weak.Upgrade();
2297 ACE_SCOPED_TRACE("FrameNode[%s][id:%d][parentId:%d]::RenderTask", self->GetTag().c_str(),
2298 self->GetId(), self->GetParent()? self->GetParent()->GetId() : -1);
2299 auto pipeline = PipelineContext::GetCurrentContext();
2300 if (pipeline) {
2301 auto id = pipeline->GetInstanceId();
2302 ArkUIPerfMonitor::GetPerfMonitor(id)->RecordRenderNode();
2303 }
2304 wrapper->FlushRender();
2305 paintProperty->CleanDirty();
2306 auto eventHub = self->GetEventHub<NG::EventHub>();
2307 if (self->GetInspectorId() || (eventHub && eventHub->HasNDKDrawCompletedCallback())) {
2308 CHECK_NULL_VOID(pipeline);
2309 pipeline->SetNeedRenderNode(weak);
2310 }
2311 if (self->IsObservedByDrawChildren()) {
2312 auto pipeline = self->GetContextRefPtr();
2313 CHECK_NULL_VOID(pipeline);
2314 auto frameNode = AceType::DynamicCast<FrameNode>(self->GetObserverParentForDrawChildren());
2315 CHECK_NULL_VOID(frameNode);
2316 pipeline->SetNeedRenderForDrawChildrenNode(WeakPtr<FrameNode>(frameNode));
2317 }
2318 };
2319 if (forceUseMainThread || wrapper->CheckShouldRunOnMain()) {
2320 return UITask(std::move(task), MAIN_TASK);
2321 }
2322 return UITask(std::move(task), wrapper->CanRunOnWhichThread());
2323 }
2324
GetLayoutConstraint() const2325 LayoutConstraintF FrameNode::GetLayoutConstraint() const
2326 {
2327 if (geometryNode_->GetParentLayoutConstraint().has_value()) {
2328 return geometryNode_->GetParentLayoutConstraint().value();
2329 }
2330 LayoutConstraintF layoutConstraint;
2331 layoutConstraint.scaleProperty = ScaleProperty::CreateScaleProperty();
2332 auto rootWidth = PipelineContext::GetCurrentRootWidth();
2333 auto rootHeight = PipelineContext::GetCurrentRootHeight();
2334 layoutConstraint.percentReference.SetWidth(rootWidth);
2335 layoutConstraint.percentReference.SetHeight(rootHeight);
2336 layoutConstraint.maxSize.SetWidth(rootWidth);
2337 layoutConstraint.maxSize.SetHeight(rootHeight);
2338 return layoutConstraint;
2339 }
2340
UpdateLayoutPropertyFlag()2341 void FrameNode::UpdateLayoutPropertyFlag()
2342 {
2343 auto selfFlag = layoutProperty_->GetPropertyChangeFlag();
2344 if (!CheckUpdateByChildRequest(selfFlag)) {
2345 return;
2346 }
2347 if (CheckForceParentMeasureFlag(selfFlag)) {
2348 return;
2349 }
2350 auto flag = PROPERTY_UPDATE_NORMAL;
2351 const auto& children = GetChildren();
2352 for (const auto& child : children) {
2353 child->UpdateLayoutPropertyFlag();
2354 child->AdjustParentLayoutFlag(flag);
2355 if (CheckForceParentMeasureFlag(selfFlag)) {
2356 break;
2357 }
2358 }
2359 if (CheckForceParentMeasureFlag(flag)) {
2360 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
2361 }
2362 }
2363
ForceUpdateLayoutPropertyFlag(PropertyChangeFlag propertyChangeFlag)2364 void FrameNode::ForceUpdateLayoutPropertyFlag(PropertyChangeFlag propertyChangeFlag)
2365 {
2366 layoutProperty_->UpdatePropertyChangeFlag(propertyChangeFlag);
2367 }
2368
AdjustParentLayoutFlag(PropertyChangeFlag & flag)2369 void FrameNode::AdjustParentLayoutFlag(PropertyChangeFlag& flag)
2370 {
2371 flag = flag | layoutProperty_->GetPropertyChangeFlag();
2372 }
2373
CreateLayoutWrapper(bool forceMeasure,bool forceLayout)2374 RefPtr<LayoutWrapperNode> FrameNode::CreateLayoutWrapper(bool forceMeasure, bool forceLayout)
2375 {
2376 return UpdateLayoutWrapper(nullptr, forceMeasure, forceLayout);
2377 }
2378
UpdateLayoutWrapper(RefPtr<LayoutWrapperNode> layoutWrapper,bool forceMeasure,bool forceLayout)2379 RefPtr<LayoutWrapperNode> FrameNode::UpdateLayoutWrapper(
2380 RefPtr<LayoutWrapperNode> layoutWrapper, bool forceMeasure, bool forceLayout)
2381 {
2382 CHECK_NULL_RETURN(layoutProperty_, nullptr);
2383 CHECK_NULL_RETURN(pattern_, nullptr);
2384 if (layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE) == VisibleType::GONE) {
2385 if (!layoutWrapper) {
2386 layoutWrapper =
2387 MakeRefPtr<LayoutWrapperNode>(WeakClaim(this), MakeRefPtr<GeometryNode>(), layoutProperty_->Clone());
2388 } else {
2389 layoutWrapper->Update(WeakClaim(this), MakeRefPtr<GeometryNode>(), layoutProperty_->Clone());
2390 }
2391 layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(nullptr, true, true));
2392 isLayoutDirtyMarked_ = false;
2393 return layoutWrapper;
2394 }
2395
2396 pattern_->BeforeCreateLayoutWrapper();
2397 if (forceMeasure) {
2398 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
2399 }
2400 if (forceLayout) {
2401 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_LAYOUT);
2402 }
2403 auto flag = layoutProperty_->GetPropertyChangeFlag();
2404 // It is necessary to copy the layoutProperty property to prevent the layoutProperty property from being
2405 // modified during the layout process, resulting in the problem of judging whether the front-end setting value
2406 // changes the next time js is executed.
2407 if (!layoutWrapper) {
2408 layoutWrapper =
2409 MakeRefPtr<LayoutWrapperNode>(WeakClaim(this), geometryNode_->Clone(), layoutProperty_->Clone());
2410 } else {
2411 layoutWrapper->Update(WeakClaim(this), geometryNode_->Clone(), layoutProperty_->Clone());
2412 }
2413 do {
2414 if (CheckNeedMeasure(flag) || forceMeasure) {
2415 layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm()));
2416 bool forceChildMeasure = CheckMeasureFlag(flag) || CheckMeasureSelfAndChildFlag(flag) || forceMeasure;
2417 UpdateChildrenLayoutWrapper(layoutWrapper, forceChildMeasure, false);
2418 break;
2419 }
2420 if (CheckNeedLayout(flag) || forceLayout) {
2421 layoutWrapper->SetLayoutAlgorithm(
2422 MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm(), true, false));
2423 UpdateChildrenLayoutWrapper(layoutWrapper, false, false);
2424 break;
2425 }
2426 layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(nullptr, true, true));
2427 } while (false);
2428 // check position flag.
2429 layoutWrapper->SetOutOfLayout(renderContext_->HasPosition());
2430 layoutWrapper->SetActive(isActive_);
2431 layoutWrapper->SetIsOverlayNode(layoutProperty_->IsOverlayNode());
2432 isLayoutDirtyMarked_ = false;
2433 return layoutWrapper;
2434 }
2435
UpdateChildrenLayoutWrapper(const RefPtr<LayoutWrapperNode> & self,bool forceMeasure,bool forceLayout)2436 void FrameNode::UpdateChildrenLayoutWrapper(const RefPtr<LayoutWrapperNode>& self, bool forceMeasure, bool forceLayout)
2437 {
2438 const auto& children = GetChildren();
2439 for (const auto& child : children) {
2440 child->AdjustLayoutWrapperTree(self, forceMeasure, forceLayout);
2441 }
2442 }
2443
AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode> & parent,bool forceMeasure,bool forceLayout)2444 void FrameNode::AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode>& parent, bool forceMeasure, bool forceLayout)
2445 {
2446 ACE_DCHECK(parent);
2447 CHECK_NULL_VOID(layoutProperty_);
2448 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
2449 if (geometryTransition != nullptr && geometryTransition->IsNodeOutAndActive(WeakClaim(this))) {
2450 return;
2451 }
2452 auto layoutWrapper = CreateLayoutWrapper(forceMeasure, forceLayout);
2453 parent->AppendChild(layoutWrapper, layoutProperty_->IsOverlayNode());
2454 }
2455
GetContentModifier()2456 RefPtr<ContentModifier> FrameNode::GetContentModifier()
2457 {
2458 CHECK_NULL_RETURN(pattern_, nullptr);
2459 auto wrapper = CreatePaintWrapper();
2460 CHECK_NULL_RETURN(wrapper, nullptr);
2461 auto paintMethod = pattern_->CreateNodePaintMethod();
2462 if (!paintMethod || extensionHandler_ || renderContext_->GetAccessibilityFocus().value_or(false)) {
2463 paintMethod = pattern_->CreateDefaultNodePaintMethod();
2464 }
2465 CHECK_NULL_RETURN(paintMethod, nullptr);
2466 auto contentModifier = DynamicCast<ContentModifier>(paintMethod->GetContentModifier(AceType::RawPtr(wrapper)));
2467 return contentModifier;
2468 }
2469
CreatePaintWrapper()2470 RefPtr<PaintWrapper> FrameNode::CreatePaintWrapper()
2471 {
2472 pattern_->BeforeCreatePaintWrapper();
2473 isRenderDirtyMarked_ = false;
2474 if (kitNode_ && kitNode_->GetPattern()) {
2475 auto method = kitNode_->GetPattern()->CreateNodePaintMethod();
2476 auto paintWrapper = MakeRefPtr<PaintWrapper>(
2477 renderContext_, geometryNode_->Clone(), paintProperty_->Clone(), extensionHandler_);
2478 paintWrapper->SetKitNodePaintMethod(method);
2479 return paintWrapper;
2480 }
2481 auto paintMethod = pattern_->CreateNodePaintMethod();
2482 if (paintMethod || extensionHandler_ || renderContext_->GetAccessibilityFocus().value_or(false)) {
2483 // It is necessary to copy the layoutProperty property to prevent the paintProperty_ property from being
2484 // modified during the paint process, resulting in the problem of judging whether the front-end setting value
2485 // changes the next time js is executed.
2486 if (!paintMethod) {
2487 paintMethod = pattern_->CreateDefaultNodePaintMethod();
2488 }
2489
2490 auto paintWrapper = MakeRefPtr<PaintWrapper>(
2491 renderContext_, geometryNode_->Clone(), paintProperty_->Clone(), extensionHandler_);
2492 paintWrapper->SetNodePaintMethod(paintMethod);
2493 return paintWrapper;
2494 }
2495 return nullptr;
2496 }
2497
PostIdleTask(std::function<void (int64_t deadline,bool canUseLongPredictTask)> && task)2498 void FrameNode::PostIdleTask(std::function<void(int64_t deadline, bool canUseLongPredictTask)>&& task)
2499 {
2500 auto context = GetContext();
2501 CHECK_NULL_VOID(context);
2502 context->AddPredictTask(std::move(task));
2503 }
2504
UpdateLayoutConstraint(const MeasureProperty & calcLayoutConstraint)2505 void FrameNode::UpdateLayoutConstraint(const MeasureProperty& calcLayoutConstraint)
2506 {
2507 layoutProperty_->UpdateCalcLayoutProperty(calcLayoutConstraint);
2508 }
2509
RebuildRenderContextTree()2510 void FrameNode::RebuildRenderContextTree()
2511 {
2512 // This function has a mirror function (XxxMultiThread) and needs to be modified synchronously.
2513 FREE_NODE_CHECK(this, RebuildRenderContextTree);
2514 if (!needSyncRenderTree_) {
2515 return;
2516 }
2517 auto pipeline = GetContextRefPtr();
2518 if (pipeline && !pipeline->CheckThreadSafe()) {
2519 LOGW("RebuildRenderContextTree doesn't run on UI thread!");
2520 }
2521 frameChildren_.clear();
2522 std::list<RefPtr<FrameNode>> children;
2523 // generate full children list, including disappear children.
2524 GenerateOneDepthVisibleFrameWithTransition(children);
2525 if (overlayNode_) {
2526 auto property = overlayNode_->GetLayoutProperty();
2527 if (property && property->GetVisibilityValue(VisibleType::VISIBLE) == VisibleType::VISIBLE) {
2528 children.push_back(overlayNode_);
2529 }
2530 }
2531 if (accessibilityFocusPaintNode_) {
2532 children.push_back(accessibilityFocusPaintNode_);
2533 }
2534 for (const auto& child : children) {
2535 frameChildren_.emplace(child);
2536 }
2537 renderContext_->RebuildFrame(this, children);
2538 pattern_->OnRebuildFrame();
2539 if (isDeleteRsNode_) {
2540 auto parentFrameNode = GetParentFrameNode();
2541 if (parentFrameNode) {
2542 parentFrameNode->MarkNeedSyncRenderTree();
2543 parentFrameNode->RebuildRenderContextTree();
2544 }
2545 }
2546 needSyncRenderTree_ = false;
2547 }
2548
MarkModifyDone()2549 void FrameNode::MarkModifyDone()
2550 {
2551 // This function has a mirror function (XxxMultiThread) and needs to be modified synchronously.
2552 FREE_NODE_CHECK(this, MarkModifyDone);
2553 pattern_->OnModifyDone();
2554 auto pipeline = PipelineContext::GetCurrentContextSafely();
2555 if (pipeline) {
2556 auto privacyManager = pipeline->GetPrivacySensitiveManager();
2557 if (privacyManager) {
2558 if (IsPrivacySensitive()) {
2559 LOGI("store sensitive node, %{public}d", nodeId_);
2560 privacyManager->StoreNode(AceType::WeakClaim(this));
2561 } else {
2562 privacyManager->RemoveNode(AceType::WeakClaim(this));
2563 }
2564 }
2565 }
2566 if (!isRestoreInfoUsed_) {
2567 isRestoreInfoUsed_ = true;
2568 int32_t restoreId = GetRestoreId();
2569 if (pipeline && restoreId >= 0) {
2570 // store distribute node
2571 pipeline->StoreNode(restoreId, AceType::WeakClaim(this));
2572 // restore distribute node info
2573 std::string restoreInfo;
2574 if (pipeline->GetRestoreInfo(restoreId, restoreInfo)) {
2575 pattern_->OnRestoreInfo(restoreInfo);
2576 }
2577 }
2578 }
2579 if (eventHub_) {
2580 eventHub_->MarkModifyDone();
2581 }
2582 renderContext_->OnModifyDone();
2583 #if (defined(__aarch64__) || defined(__x86_64__))
2584 if (Recorder::IsCacheAvaliable()) {
2585 auto pipeline = PipelineContext::GetCurrentContext();
2586 CHECK_NULL_VOID(pipeline);
2587 pipeline->AddAfterRenderTask([weak = WeakPtr(pattern_)]() {
2588 auto pattern = weak.Upgrade();
2589 CHECK_NULL_VOID(pattern);
2590 pattern->OnAfterModifyDone();
2591 });
2592 }
2593 #endif
2594 }
2595
OnMountToParentDone()2596 [[deprecated("using AfterMountToParent")]] void FrameNode::OnMountToParentDone()
2597 {
2598 pattern_->OnMountToParentDone();
2599 }
2600
AfterMountToParent()2601 void FrameNode::AfterMountToParent()
2602 {
2603 if (pattern_) {
2604 pattern_->AfterMountToParent();
2605 }
2606 }
2607
FlushUpdateAndMarkDirty()2608 void FrameNode::FlushUpdateAndMarkDirty()
2609 {
2610 MarkDirtyNode();
2611 }
2612
MarkDirtyNode(PropertyChangeFlag extraFlag)2613 void FrameNode::MarkDirtyNode(PropertyChangeFlag extraFlag)
2614 {
2615 // This function has a mirror function (XxxMultiThread) and needs to be modified synchronously.
2616 FREE_NODE_CHECK(this, MarkDirtyNode, extraFlag);
2617 if (IsFreeze()) {
2618 // store the flag.
2619 layoutProperty_->UpdatePropertyChangeFlag(extraFlag);
2620 paintProperty_->UpdatePropertyChangeFlag(extraFlag);
2621 return;
2622 }
2623 if (CheckNeedMakePropertyDiff(extraFlag)) {
2624 if (isPropertyDiffMarked_) {
2625 return;
2626 }
2627 auto context = GetContextWithCheck();
2628 CHECK_NULL_VOID(context);
2629 context->AddDirtyPropertyNode(Claim(this));
2630 isPropertyDiffMarked_ = true;
2631 return;
2632 }
2633 MarkDirtyNode(IsMeasureBoundary(), IsRenderBoundary(), extraFlag);
2634 }
2635
ProcessFreezeNode()2636 void FrameNode::ProcessFreezeNode()
2637 {
2638 MarkDirtyNode();
2639 }
2640
OnFreezeStateChange()2641 void FrameNode::OnFreezeStateChange()
2642 {
2643 if (IsFreeze()) {
2644 return;
2645 }
2646 // unlock freeze, mark dirty to process freeze node.
2647 auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
2648 auto paintFlag = paintProperty_->GetPropertyChangeFlag();
2649 if (CheckNoChanged(layoutFlag | paintFlag)) {
2650 return;
2651 }
2652 auto pipeline = GetContext();
2653 CHECK_NULL_VOID(pipeline);
2654 pipeline->AddDirtyFreezeNode(this);
2655 }
2656
GetAncestorNodeOfFrame(bool checkBoundary) const2657 RefPtr<FrameNode> FrameNode::GetAncestorNodeOfFrame(bool checkBoundary) const
2658 {
2659 if (checkBoundary && IsWindowBoundary()) {
2660 return nullptr;
2661 }
2662 auto parent = GetParent();
2663 while (parent) {
2664 auto parentFrame = DynamicCast<FrameNode>(parent);
2665 if (parentFrame) {
2666 return parentFrame;
2667 }
2668 parent = parent->GetParent();
2669 }
2670 return nullptr;
2671 }
2672
GetPageNode()2673 RefPtr<FrameNode> FrameNode::GetPageNode()
2674 {
2675 if (tag_ == "page") {
2676 return Claim(this);
2677 }
2678 auto parent = GetParent();
2679 while (parent && parent->GetTag() != "page") {
2680 parent = parent->GetParent();
2681 }
2682 return AceType::DynamicCast<FrameNode>(parent);
2683 }
2684
GetFirstAutoFillContainerNode()2685 RefPtr<FrameNode> FrameNode::GetFirstAutoFillContainerNode()
2686 {
2687 if (IsAutoFillContainerNode()) {
2688 return Claim(this);
2689 }
2690 auto parent = GetParent();
2691 while (parent && !parent->IsAutoFillContainerNode()) {
2692 parent = parent->GetParent();
2693 }
2694 return AceType::DynamicCast<FrameNode>(parent);
2695 }
2696
NotifyFillRequestSuccess(RefPtr<ViewDataWrap> viewDataWrap,RefPtr<PageNodeInfoWrap> nodeWrap,AceAutoFillType autoFillType)2697 void FrameNode::NotifyFillRequestSuccess(
2698 RefPtr<ViewDataWrap> viewDataWrap, RefPtr<PageNodeInfoWrap> nodeWrap, AceAutoFillType autoFillType)
2699 {
2700 if (pattern_) {
2701 pattern_->NotifyFillRequestSuccess(viewDataWrap, nodeWrap, autoFillType);
2702 }
2703 }
2704
NotifyFillRequestFailed(int32_t errCode,const std::string & fillContent,bool isPopup)2705 void FrameNode::NotifyFillRequestFailed(int32_t errCode, const std::string& fillContent, bool isPopup)
2706 {
2707 if (pattern_) {
2708 pattern_->NotifyFillRequestFailed(errCode, fillContent, isPopup);
2709 }
2710 }
2711
MarkNeedRenderOnly()2712 void FrameNode::MarkNeedRenderOnly()
2713 {
2714 MarkNeedRender(IsRenderBoundary());
2715 }
2716
MarkNeedRender(bool isRenderBoundary)2717 void FrameNode::MarkNeedRender(bool isRenderBoundary)
2718 {
2719 // This function has a mirror function (XxxMultiThread) and needs to be modified synchronously.
2720 FREE_NODE_CHECK(this, MarkNeedRender, isRenderBoundary);
2721 auto context = GetContext();
2722 CHECK_NULL_VOID(context);
2723 // If it has dirtyLayoutBox, need to mark dirty after layout done.
2724 paintProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_RENDER);
2725 if (isRenderDirtyMarked_ || isLayoutDirtyMarked_) {
2726 return;
2727 }
2728 isRenderDirtyMarked_ = true;
2729 if (isRenderBoundary) {
2730 context->AddDirtyRenderNode(Claim(this));
2731 return;
2732 }
2733 auto parent = GetAncestorNodeOfFrame(false);
2734 if (parent) {
2735 parent->MarkDirtyNode(PROPERTY_UPDATE_RENDER_BY_CHILD_REQUEST);
2736 }
2737 }
2738
RequestParentDirty()2739 bool FrameNode::RequestParentDirty()
2740 {
2741 auto parent = GetAncestorNodeOfFrame(false);
2742 CHECK_NULL_RETURN(parent, false);
2743 parent->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
2744 return true;
2745 }
2746
MarkDirtyNode(bool isMeasureBoundary,bool isRenderBoundary,PropertyChangeFlag extraFlag)2747 void FrameNode::MarkDirtyNode(bool isMeasureBoundary, bool isRenderBoundary, PropertyChangeFlag extraFlag)
2748 {
2749 layoutProperty_->UpdatePropertyChangeFlag(extraFlag);
2750 paintProperty_->UpdatePropertyChangeFlag(extraFlag);
2751 auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
2752 auto paintFlag = paintProperty_->GetPropertyChangeFlag();
2753 if (CheckNoChanged(layoutFlag | paintFlag)) {
2754 return;
2755 }
2756 auto context = GetContext();
2757 CHECK_NULL_VOID(context);
2758
2759 if (CheckNeedRequestMeasureAndLayout(layoutFlag)) {
2760 if ((!isMeasureBoundary && IsNeedRequestParentMeasure())) {
2761 if (RequestParentDirty()) {
2762 return;
2763 }
2764 }
2765 if (isLayoutDirtyMarked_) {
2766 return;
2767 }
2768 isLayoutDirtyMarked_ = true;
2769 context->AddDirtyLayoutNode(Claim(this));
2770 return;
2771 }
2772 layoutProperty_->CleanDirty();
2773 MarkNeedRender(isRenderBoundary);
2774 }
2775
IsNeedRequestParentMeasure() const2776 bool FrameNode::IsNeedRequestParentMeasure() const
2777 {
2778 auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
2779 if (layoutFlag == PROPERTY_UPDATE_BY_CHILD_REQUEST) {
2780 const auto& calcLayoutConstraint = layoutProperty_->GetCalcLayoutConstraint();
2781 if (calcLayoutConstraint && calcLayoutConstraint->selfIdealSize &&
2782 calcLayoutConstraint->selfIdealSize->IsValid()) {
2783 return false;
2784 }
2785 }
2786 return CheckNeedRequestParentMeasure(layoutFlag);
2787 }
2788
OnGenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>> & visibleList)2789 void FrameNode::OnGenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>>& visibleList)
2790 {
2791 if (isLayoutNode_) {
2792 UINode::GenerateOneDepthVisibleFrame(visibleList);
2793 if (overlayNode_) {
2794 visibleList.emplace_back(overlayNode_);
2795 }
2796 return;
2797 }
2798 if (isActive_ && IsVisible()) {
2799 visibleList.emplace_back(Claim(this));
2800 }
2801 }
2802
OnGenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>> & allList)2803 void FrameNode::OnGenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>>& allList)
2804 {
2805 allList.emplace_back(Claim(this));
2806 }
2807
OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>> & visibleList)2808 void FrameNode::OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>>& visibleList)
2809 {
2810 if (isLayoutNode_) {
2811 UINode::GenerateOneDepthVisibleFrameWithTransition(visibleList);
2812 if (overlayNode_) {
2813 visibleList.emplace_back(overlayNode_);
2814 }
2815 return;
2816 }
2817
2818 auto context = GetRenderContext();
2819 CHECK_NULL_VOID(context);
2820 // skip if 1.not active or 2.not visible and has no transition out animation.
2821 if (!isActive_ || (!IsVisible() && !context->HasTransitionOutAnimation())) {
2822 return;
2823 }
2824 visibleList.emplace_back(Claim(this));
2825 }
2826
OnGenerateOneDepthVisibleFrameWithOffset(std::list<RefPtr<FrameNode>> & visibleList,OffsetF & offset)2827 void FrameNode::OnGenerateOneDepthVisibleFrameWithOffset(std::list<RefPtr<FrameNode>>& visibleList, OffsetF& offset)
2828 {
2829 if (isLayoutNode_) {
2830 isFind_ = true;
2831 offset += GetGeometryNode()->GetFrameOffset();
2832 UINode::GenerateOneDepthVisibleFrameWithOffset(visibleList, offset);
2833 if (overlayNode_) {
2834 visibleList.emplace_back(overlayNode_);
2835 }
2836 return;
2837 }
2838
2839 auto context = GetRenderContext();
2840 CHECK_NULL_VOID(context);
2841 // skip if 1.not active or 2.not visible and has no transition out animation.
2842 if (!isActive_ || (!IsVisible() && !context->HasTransitionOutAnimation())) {
2843 return;
2844 }
2845 visibleList.emplace_back(Claim(this));
2846 }
2847
IsMeasureBoundary()2848 bool FrameNode::IsMeasureBoundary()
2849 {
2850 return isMeasureBoundary_ || pattern_->IsMeasureBoundary();
2851 }
2852
IsRenderBoundary()2853 bool FrameNode::IsRenderBoundary()
2854 {
2855 return pattern_->IsRenderBoundary();
2856 }
2857
GetPattern() const2858 const RefPtr<Pattern>& FrameNode::GetPattern() const
2859 {
2860 return pattern_;
2861 }
2862
IsAtomicNode() const2863 bool FrameNode::IsAtomicNode() const
2864 {
2865 if (kitNode_ && kitNode_->GetPattern()) {
2866 return kitNode_->GetPattern()->IsAtomicNode();
2867 }
2868 return pattern_->IsAtomicNode();
2869 }
2870
GetHitTestMode() const2871 HitTestMode FrameNode::GetHitTestMode() const
2872 {
2873 auto gestureHub = eventHub_ ? eventHub_->GetGestureEventHub() : nullptr;
2874 return gestureHub ? gestureHub->GetHitTestMode() : HitTestMode::HTMDEFAULT;
2875 }
2876
SetHitTestMode(HitTestMode mode)2877 void FrameNode::SetHitTestMode(HitTestMode mode)
2878 {
2879 auto gestureHub = GetOrCreateGestureEventHub();
2880 CHECK_NULL_VOID(gestureHub);
2881 gestureHub->SetHitTestMode(mode);
2882 }
2883
GetTouchable() const2884 bool FrameNode::GetTouchable() const
2885 {
2886 CHECK_NULL_RETURN(eventHub_, true);
2887 auto gestureHub = eventHub_->GetGestureEventHub();
2888 return gestureHub ? gestureHub->GetTouchable() : true;
2889 }
2890
GetMonopolizeEvents() const2891 bool FrameNode::GetMonopolizeEvents() const
2892 {
2893 CHECK_NULL_RETURN(eventHub_, false);
2894 auto gestureHub = eventHub_->GetGestureEventHub();
2895 return gestureHub ? gestureHub->GetMonopolizeEvents() : false;
2896 }
2897
2898 // get paint rect include graphic properties
GetPaintRectWithTransform() const2899 RectF FrameNode::GetPaintRectWithTransform() const
2900 {
2901 return renderContext_->GetPaintRectWithTransform();
2902 }
2903
GetTransformScale() const2904 VectorF FrameNode::GetTransformScale() const
2905 {
2906 return renderContext_->GetTransformScaleValue({ 1.0f, 1.0f });
2907 }
2908
IsPaintRectWithTransformValid()2909 bool FrameNode::IsPaintRectWithTransformValid()
2910 {
2911 auto& paintRectWithTransform = GetOrRefreshMatrixFromCache().paintRectWithTransform;
2912 if (NearZero(paintRectWithTransform.Width()) || NearZero(paintRectWithTransform.Height())) {
2913 return true;
2914 }
2915 return false;
2916 }
2917
IsOutOfTouchTestRegion(const PointF & parentRevertPoint,const TouchEvent & touchEvent,std::vector<RectF> * regionList)2918 bool FrameNode::IsOutOfTouchTestRegion(const PointF& parentRevertPoint, const TouchEvent& touchEvent,
2919 std::vector<RectF>* regionList)
2920 {
2921 bool isInChildRegion = false;
2922 auto paintRect = renderContext_->GetPaintRectWithoutTransform();
2923 if (pattern_->IsResponseRegionExpandingNeededForStylus(touchEvent)) {
2924 paintRect = pattern_->ExpandDefaultResponseRegion(paintRect);
2925 }
2926 std::vector<RectF> responseRegionList;
2927 if (regionList) {
2928 responseRegionList = *regionList;
2929 } else {
2930 responseRegionList = GetResponseRegionList(paintRect, static_cast<int32_t>(touchEvent.sourceType));
2931 }
2932
2933 auto revertPoint = parentRevertPoint;
2934 MapPointTo(revertPoint, GetOrRefreshMatrixFromCache().revertMatrix);
2935 auto subRevertPoint = revertPoint - paintRect.GetOffset();
2936 auto clip = renderContext_->GetClipEdge().value_or(false);
2937 if (!InResponseRegionList(revertPoint, responseRegionList) || !GetTouchable()) {
2938 if (clip) {
2939 return true;
2940 }
2941 for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
2942 const auto& child = iter->Upgrade();
2943 if (child && !child->IsOutOfTouchTestRegion(subRevertPoint, touchEvent)) {
2944 isInChildRegion = true;
2945 break;
2946 }
2947 }
2948 if (!isInChildRegion) {
2949 return true;
2950 }
2951 }
2952 return false;
2953 }
2954
AddJudgeToTargetComponent(RefPtr<TargetComponent> & targetComponent)2955 void FrameNode::AddJudgeToTargetComponent(RefPtr<TargetComponent>& targetComponent)
2956 {
2957 CHECK_NULL_VOID(eventHub_);
2958 auto gestureHub = eventHub_->GetGestureEventHub();
2959 if (gestureHub) {
2960 auto callback = gestureHub->GetOnGestureJudgeBeginCallback();
2961 targetComponent->SetOnGestureJudgeBegin(std::move(callback));
2962 auto callbackNative = gestureHub->GetOnGestureJudgeNativeBeginCallback();
2963 if (callbackNative) {
2964 targetComponent->SetOnGestureJudgeNativeBegin(std::move(callbackNative));
2965 }
2966
2967 if (!targetComponent->IsInnerNodeGestureRecognizerJudgeSet()) {
2968 auto gestureRecognizerJudgeCallback = gestureHub->GetOnGestureRecognizerJudgeBegin();
2969 targetComponent->SetOnGestureRecognizerJudgeBegin(std::move(gestureRecognizerJudgeCallback));
2970 }
2971
2972 auto pattern = GetPattern();
2973 if (pattern) {
2974 if (GetExposeInnerGestureFlag()) {
2975 auto gestureRecognizerJudgeCallback = gestureHub->GetOnGestureRecognizerJudgeBegin();
2976 pattern->AddInnerOnGestureRecognizerJudgeBegin(std::move(gestureRecognizerJudgeCallback));
2977 } else {
2978 pattern->RecoverInnerOnGestureRecognizerJudgeBegin();
2979 }
2980 }
2981 }
2982 }
2983
AddNodeToRegisterTouchTest()2984 void FrameNode::AddNodeToRegisterTouchTest()
2985 {
2986 auto context = GetContext();
2987 CHECK_NULL_VOID(context);
2988 auto eventMgr = context->GetEventManager();
2989 CHECK_NULL_VOID(eventMgr);
2990 auto gestureEventHub = GetOrCreateGestureEventHub();
2991 CHECK_NULL_VOID(gestureEventHub);
2992 if (!gestureEventHub->GetOnTouchTestDoneCallbackForInner() && !gestureEventHub->GetOnTouchTestDoneCallback()) {
2993 return;
2994 }
2995 eventMgr->AddTouchDoneFrameNode(AceType::WeakClaim(this));
2996 }
2997
CheckResponseRegionForStylus(RectF & rect,const TouchEvent & touchEvent)2998 RectF FrameNode::CheckResponseRegionForStylus(RectF& rect, const TouchEvent& touchEvent)
2999 {
3000 if (!pattern_ || !pattern_->IsResponseRegionExpandingNeededForStylus(touchEvent)) {
3001 return rect;
3002 }
3003 return pattern_->ExpandDefaultResponseRegion(rect);
3004 }
3005
TouchTest(const PointF & globalPoint,const PointF & parentLocalPoint,const PointF & parentRevertPoint,TouchRestrict & touchRestrict,TouchTestResult & result,int32_t touchId,ResponseLinkResult & responseLinkResult,bool isDispatch)3006 HitTestResult FrameNode::TouchTest(const PointF& globalPoint, const PointF& parentLocalPoint,
3007 const PointF& parentRevertPoint, TouchRestrict& touchRestrict, TouchTestResult& result, int32_t touchId,
3008 ResponseLinkResult& responseLinkResult, bool isDispatch)
3009 {
3010 auto& cacheMatrixInfo = GetOrRefreshMatrixFromCache();
3011 auto paintRect = cacheMatrixInfo.paintRectWithTransform;
3012 if (!isActive_) {
3013 TAG_LOGW(AceLogTag::ACE_UIEVENT, "%{public}s/%{public}d is inActive, needn't do touch test. Rect is %{public}s",
3014 tag_.c_str(), nodeId_, paintRect.ToString().c_str());
3015 int32_t parentId = -1;
3016 auto parent = GetAncestorNodeOfFrame(true);
3017 if (parent) {
3018 parentId = parent->GetId();
3019 }
3020 AddFrameNodeSnapshot(true, parentId, std::vector<RectF>(), EventTreeType::TOUCH);
3021
3022 return HitTestResult::OUT_OF_REGION;
3023 }
3024
3025 if (eventHub_ && !eventHub_->IsEnabled()) {
3026 if (hasBindTips_) {
3027 TipsTouchTest(globalPoint, parentLocalPoint, parentRevertPoint, touchRestrict, result,
3028 responseLinkResult, isDispatch);
3029 }
3030 TAG_LOGW(AceLogTag::ACE_UIEVENT, "%{public}s/%{public}d eventHub not enabled, needn't do touch test",
3031 tag_.c_str(), nodeId_);
3032 return HitTestResult::OUT_OF_REGION;
3033 }
3034
3035 auto origRect = renderContext_->GetPaintRectWithoutTransform();
3036 auto localMat = cacheMatrixInfo.localMatrix;
3037 if (!touchRestrict.touchEvent.isMouseTouchTest) {
3038 localMat_ = localMat;
3039 }
3040
3041 int32_t parentId = -1;
3042 auto parent = GetAncestorNodeOfFrame(true);
3043 if (parent) {
3044 parentId = parent->GetId();
3045 }
3046 auto checkedResponseRegionForStylus = CheckResponseRegionForStylus(origRect, touchRestrict.touchEvent);
3047 auto responseRegionList =
3048 GetResponseRegionList(checkedResponseRegionForStylus, static_cast<int32_t>(touchRestrict.sourceType));
3049 if (SystemProperties::GetDebugEnabled()) {
3050 TAG_LOGD(AceLogTag::ACE_UIEVENT, "TouchTest: point is " SEC_PLD(%{public}s) " in %{public}s, depth: %{public}d",
3051 SEC_PARAM(parentRevertPoint.ToString().c_str()), tag_.c_str(), depth_);
3052 for ([[maybe_unused]] const auto& rect : responseRegionList) {
3053 TAG_LOGD(AceLogTag::ACE_UIEVENT, "TouchTest: responseRegionList is " SEC_PLD(%{public}s)
3054 ", point is " SEC_PLD(%{public}s),
3055 SEC_PARAM(rect.ToString().c_str()), SEC_PARAM(parentRevertPoint.ToString().c_str()));
3056 }
3057 }
3058 {
3059 ACE_DEBUG_SCOPED_TRACE("FrameNode::IsOutOfTouchTestRegion");
3060 bool isOutOfRegion = IsOutOfTouchTestRegion(parentRevertPoint, touchRestrict.touchEvent, &responseRegionList);
3061 AddFrameNodeSnapshot(!isOutOfRegion, parentId, responseRegionList, touchRestrict.touchTestType);
3062 if ((!isDispatch) && isOutOfRegion) {
3063 return HitTestResult::OUT_OF_REGION;
3064 }
3065 }
3066
3067 RefPtr<TargetComponent> targetComponent;
3068 if (targetComponent_.Upgrade()) {
3069 targetComponent = targetComponent_.Upgrade();
3070 } else {
3071 targetComponent = MakeRefPtr<TargetComponent>();
3072 targetComponent_ = targetComponent;
3073 }
3074 targetComponent->SetNode(WeakClaim(this));
3075
3076 HitTestResult testResult = HitTestResult::OUT_OF_REGION;
3077 bool preventBubbling = false;
3078 bool blockHierarchy = false;
3079 // Child nodes are repackaged into gesture groups (parallel gesture groups, exclusive gesture groups, etc.)
3080 // based on the gesture attributes set by the current parent node (high and low priority, parallel gestures,
3081 // etc.), the newComingTargets is the template object to collect child nodes gesture and used by gestureHub to
3082 // pack gesture group.
3083 TouchTestResult newComingTargets;
3084 auto tmp = parentLocalPoint - paintRect.GetOffset();
3085 auto preLocation = tmp;
3086 renderContext_->GetPointWithTransform(tmp);
3087 const auto localPoint = tmp;
3088 auto localTransformOffset = preLocation - localPoint;
3089
3090 auto revertPoint = parentRevertPoint;
3091 MapPointTo(revertPoint, cacheMatrixInfo.revertMatrix);
3092 auto subRevertPoint = revertPoint - origRect.GetOffset();
3093 bool consumed = false;
3094
3095 HitTestMode onTouchInterceptresult = HitTestMode::HTMDEFAULT;
3096 if (touchRestrict.inputEventType != InputEventType::MOUSE_BUTTON &&
3097 touchRestrict.touchEvent.type != TouchType::HOVER_ENTER) {
3098 onTouchInterceptresult = TriggerOnTouchIntercept(touchRestrict.touchEvent);
3099 }
3100 TouchResult touchRes;
3101 if (onTouchInterceptresult != HitTestMode::HTMBLOCK &&
3102 onTouchInterceptresult != HitTestMode::HTMBLOCK_DESCENDANTS) {
3103 std::vector<TouchTestInfo> touchInfos;
3104 CollectTouchInfos(globalPoint, subRevertPoint, touchInfos);
3105 touchRes = GetOnChildTouchTestRet(touchInfos);
3106 if ((touchRes.strategy != TouchTestStrategy::DEFAULT) && touchRes.id.empty()) {
3107 TAG_LOGW(AceLogTag::ACE_UIEVENT, "onChildTouchTest result is: "
3108 "id = " SEC_PLD(%{public}s) ", strategy = %{public}d.",
3109 SEC_PARAM(touchRes.id.c_str()), static_cast<int32_t>(touchRes.strategy));
3110 touchRes.strategy = TouchTestStrategy::DEFAULT;
3111 }
3112
3113 auto childNode = GetDispatchFrameNode(touchRes);
3114 if (childNode != nullptr) {
3115 TAG_LOGD(AceLogTag::ACE_UIEVENT, SEC_PLD(%{public}s) " do TouchTest, parameter isDispatch is true.",
3116 SEC_PARAM(childNode->GetInspectorId()->c_str()));
3117 auto hitResult = childNode->TouchTest(globalPoint, localPoint, subRevertPoint, touchRestrict,
3118 newComingTargets, touchId, responseLinkResult, true);
3119 if (touchRes.strategy == TouchTestStrategy::FORWARD ||
3120 touchRes.strategy == TouchTestStrategy::FORWARD_COMPETITION) {
3121 touchRestrict.childTouchTestList.emplace_back(touchRes.id);
3122 }
3123 if (hitResult == HitTestResult::STOP_BUBBLING) {
3124 preventBubbling = true;
3125 consumed = true;
3126 }
3127
3128 if (hitResult == HitTestResult::BUBBLING) {
3129 consumed = true;
3130 }
3131 }
3132 }
3133 for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
3134 if (GetHitTestMode() == HitTestMode::HTMBLOCK || GetHitTestMode() == HitTestMode::HTMBLOCK_DESCENDANTS) {
3135 break;
3136 }
3137 if (onTouchInterceptresult != HitTestMode::HTMBLOCK &&
3138 onTouchInterceptresult != HitTestMode::HTMBLOCK_DESCENDANTS) {
3139 if (touchRes.strategy == TouchTestStrategy::FORWARD) {
3140 break;
3141 }
3142 }
3143
3144 const auto& child = iter->Upgrade();
3145 if (!child) {
3146 continue;
3147 }
3148 if (onTouchInterceptresult != HitTestMode::HTMBLOCK &&
3149 onTouchInterceptresult != HitTestMode::HTMBLOCK_DESCENDANTS) {
3150 std::string id;
3151 if (child->GetInspectorId().has_value()) {
3152 id = child->GetInspectorId().value();
3153 }
3154 if (touchRes.strategy == TouchTestStrategy::FORWARD_COMPETITION && touchRes.id == id) {
3155 continue;
3156 }
3157 }
3158
3159 auto childHitResult = child->TouchTest(
3160 globalPoint, localPoint, subRevertPoint, touchRestrict, newComingTargets, touchId, responseLinkResult);
3161 if (childHitResult == HitTestResult::STOP_BUBBLING) {
3162 preventBubbling = true;
3163 consumed = true;
3164 if ((child->GetHitTestMode() == HitTestMode::HTMBLOCK) ||
3165 (child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
3166 (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ||
3167 ((child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT) && IsExclusiveEventForChild())) {
3168 break;
3169 }
3170 }
3171
3172 if (childHitResult == HitTestResult::BLOCK_HIERARCHY) {
3173 blockHierarchy = true;
3174 consumed = true;
3175 break;
3176 }
3177
3178 // In normal process, the node block the brother node.
3179 if (childHitResult == HitTestResult::BUBBLING &&
3180 ((child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
3181 (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ||
3182 ((child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT &&
3183 child->GetHitTestMode() != HitTestMode::HTMBLOCK_DESCENDANTS) &&
3184 IsExclusiveEventForChild()))) {
3185 consumed = true;
3186 break;
3187 }
3188 }
3189
3190 AddJudgeToTargetComponent(targetComponent);
3191 AddNodeToRegisterTouchTest();
3192
3193 // first update HitTestResult by children status.
3194 if (consumed) {
3195 if (GetHitTestMode() == HitTestMode::HTMBLOCK_HIERARCHY) {
3196 testResult = HitTestResult::BLOCK_HIERARCHY;
3197 } else {
3198 if (blockHierarchy) {
3199 testResult = HitTestResult::BLOCK_HIERARCHY;
3200 } else {
3201 testResult = preventBubbling ? HitTestResult::STOP_BUBBLING : HitTestResult::BUBBLING;
3202 }
3203 }
3204 consumed = false;
3205 } else {
3206 if (GetHitTestMode() == HitTestMode::HTMBLOCK) {
3207 testResult = HitTestResult::STOP_BUBBLING;
3208 }
3209 if (GetHitTestMode() == HitTestMode::HTMBLOCK_HIERARCHY) {
3210 testResult = HitTestResult::BLOCK_HIERARCHY;
3211 }
3212 if (GetHitTestMode() == HitTestMode::HTMBLOCK_DESCENDANTS) {
3213 testResult = HitTestResult::BUBBLING;
3214 }
3215 }
3216
3217 if (!preventBubbling && !blockHierarchy && (GetHitTestMode() != HitTestMode::HTMNONE) &&
3218 (GetHitTestMode() != HitTestMode::HTMBLOCK_DESCENDANTS) &&
3219 (isDispatch || (InResponseRegionList(revertPoint, responseRegionList)))) {
3220 pattern_->OnTouchTestHit(touchRestrict.hitTestType);
3221 consumed = true;
3222 if (touchRestrict.hitTestType == SourceType::TOUCH) {
3223 auto gestureHub = GetOrCreateGestureEventHub();
3224 if (gestureHub) {
3225 TouchTestResult finalResult;
3226 ResponseLinkResult newComingResponseLinkTargets;
3227 const auto coordinateOffset = globalPoint - localPoint - localTransformOffset;
3228 preventBubbling = gestureHub->ProcessTouchTestHit(coordinateOffset, touchRestrict, newComingTargets,
3229 finalResult, touchId, localPoint, targetComponent, newComingResponseLinkTargets);
3230 newComingTargets.swap(finalResult);
3231 TriggerShouldParallelInnerWith(newComingResponseLinkTargets, responseLinkResult);
3232 responseLinkResult.splice(responseLinkResult.end(), std::move(newComingResponseLinkTargets));
3233 }
3234 } else if (touchRestrict.hitTestType == SourceType::MOUSE) {
3235 preventBubbling = ProcessMouseTestHit(globalPoint, localPoint, touchRestrict, newComingTargets);
3236 }
3237 }
3238
3239 result.splice(result.end(), std::move(newComingTargets));
3240 if (touchRestrict.hitTestType == SourceType::TOUCH) {
3241 // combine into exclusive recognizer group.
3242 auto gestureHub = GetOrCreateGestureEventHub();
3243 if (gestureHub) {
3244 gestureHub->CombineIntoExclusiveRecognizer(globalPoint, localPoint, result, touchId);
3245 }
3246 }
3247
3248 // consumed by children and return result.
3249 if (!consumed) {
3250 return testResult;
3251 }
3252
3253 if (testResult == HitTestResult::OUT_OF_REGION) {
3254 // consume only by self.
3255 if (preventBubbling) {
3256 return HitTestResult::STOP_BUBBLING;
3257 }
3258 return (GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ? HitTestResult::SELF_TRANSPARENT
3259 : HitTestResult::BUBBLING;
3260 }
3261 // consume by self and children.
3262 return testResult;
3263 }
3264
TipsTouchTest(const PointF & globalPoint,const PointF & parentLocalPoint,const PointF & parentRevertPoint,TouchRestrict & touchRestrict,TouchTestResult & result,ResponseLinkResult & responseLinkResult,bool isDispatch)3265 void FrameNode::TipsTouchTest(const PointF& globalPoint, const PointF& parentLocalPoint,
3266 const PointF& parentRevertPoint, TouchRestrict& touchRestrict, TouchTestResult& result,
3267 ResponseLinkResult& responseLinkResult, bool isDispatch)
3268 {
3269 auto& cacheMatrixInfo = GetOrRefreshMatrixFromCache();
3270 auto paintRect = cacheMatrixInfo.paintRectWithTransform;
3271 auto defaultResponseRegion = renderContext_->GetPaintRectWithoutTransform();
3272 auto responseRegionList =
3273 GetResponseRegionList(defaultResponseRegion, static_cast<int32_t>(touchRestrict.sourceType));
3274 RefPtr<TargetComponent> targetComponent = targetComponent_.Upgrade();
3275 if (!targetComponent) {
3276 targetComponent = MakeRefPtr<TargetComponent>();
3277 targetComponent_ = targetComponent;
3278 }
3279 targetComponent->SetNode(WeakClaim(this));
3280 TouchTestResult newComingTargets;
3281 auto tmp = parentLocalPoint - paintRect.GetOffset();
3282 renderContext_->GetPointWithTransform(tmp);
3283 const auto localPoint = tmp;
3284 auto revertPoint = parentRevertPoint;
3285 if ((GetHitTestMode() != HitTestMode::HTMNONE) &&
3286 (isDispatch || (InResponseRegionList(revertPoint, responseRegionList)))) {
3287 if (touchRestrict.hitTestType == SourceType::MOUSE) {
3288 ProcessTipsMouseTestHit(globalPoint, localPoint, touchRestrict, newComingTargets);
3289 }
3290 }
3291 result.splice(result.end(), std::move(newComingTargets));
3292 }
3293
ProcessMouseTestHit(const PointF & globalPoint,const PointF & localPoint,TouchRestrict & touchRestrict,TouchTestResult & newComingTargets)3294 bool FrameNode::ProcessMouseTestHit(const PointF& globalPoint, const PointF& localPoint,
3295 TouchRestrict& touchRestrict, TouchTestResult& newComingTargets)
3296 {
3297 CHECK_NULL_RETURN(eventHub_, false);
3298 auto mouseHub = eventHub_->GetInputEventHub();
3299 if (!mouseHub) {
3300 return false;
3301 }
3302
3303 const auto coordinateOffset = globalPoint - localPoint;
3304 if (touchRestrict.touchEvent.IsPenHoverEvent()) {
3305 return mouseHub->ProcessPenHoverTestHit(coordinateOffset, newComingTargets);
3306 }
3307
3308 return mouseHub->ProcessMouseTestHit(coordinateOffset, newComingTargets);
3309 }
3310
ProcessTipsMouseTestHit(const PointF & globalPoint,const PointF & localPoint,TouchRestrict & touchRestrict,TouchTestResult & newComingTargets)3311 bool FrameNode::ProcessTipsMouseTestHit(const PointF& globalPoint, const PointF& localPoint,
3312 TouchRestrict& touchRestrict, TouchTestResult& newComingTargets)
3313 {
3314 CHECK_NULL_RETURN(eventHub_, false);
3315 auto mouseHub = eventHub_->GetInputEventHub();
3316 if (!mouseHub) {
3317 return false;
3318 }
3319 const auto coordinateOffset = globalPoint - localPoint;
3320 return mouseHub->ProcessTipsMouseTestHit(coordinateOffset, newComingTargets);
3321 }
3322
GetResponseRegionList(const RectF & rect,int32_t sourceType)3323 std::vector<RectF> FrameNode::GetResponseRegionList(const RectF& rect, int32_t sourceType)
3324 {
3325 std::vector<RectF> responseRegionList;
3326 auto gestureHub = eventHub_ ? eventHub_->GetGestureEventHub() : nullptr;
3327 if (!gestureHub) {
3328 responseRegionList.emplace_back(rect);
3329 return responseRegionList;
3330 }
3331 auto scaleProperty = ScaleProperty::CreateScaleProperty(GetContext());
3332 bool isMouseEvent = (static_cast<SourceType>(sourceType) == SourceType::MOUSE);
3333 if (isMouseEvent) {
3334 if (gestureHub->GetResponseRegion().empty() && (gestureHub->GetMouseResponseRegion().empty())) {
3335 responseRegionList.emplace_back(rect);
3336 return responseRegionList;
3337 }
3338 } else {
3339 if (gestureHub->GetResponseRegion().empty()) {
3340 responseRegionList.emplace_back(rect);
3341 return responseRegionList;
3342 }
3343 }
3344
3345 if (isMouseEvent && (!gestureHub->GetMouseResponseRegion().empty())) {
3346 for (const auto& region : gestureHub->GetMouseResponseRegion()) {
3347 auto x = ConvertToPx(region.GetOffset().GetX(), scaleProperty, rect.Width());
3348 auto y = ConvertToPx(region.GetOffset().GetY(), scaleProperty, rect.Height());
3349 auto width = ConvertToPx(region.GetWidth(), scaleProperty, rect.Width());
3350 auto height = ConvertToPx(region.GetHeight(), scaleProperty, rect.Height());
3351 if (!x.has_value() || !y.has_value() || !width.has_value() || !height.has_value()) {
3352 continue;
3353 }
3354 RectF mouseRegion(rect.GetOffset().GetX() + x.value(), rect.GetOffset().GetY() + y.value(), width.value(),
3355 height.value());
3356 responseRegionList.emplace_back(mouseRegion);
3357 }
3358 return responseRegionList;
3359 }
3360 for (const auto& region : gestureHub->GetResponseRegion()) {
3361 auto x = ConvertToPx(region.GetOffset().GetX(), scaleProperty, rect.Width());
3362 auto y = ConvertToPx(region.GetOffset().GetY(), scaleProperty, rect.Height());
3363 auto width = ConvertToPx(region.GetWidth(), scaleProperty, rect.Width());
3364 auto height = ConvertToPx(region.GetHeight(), scaleProperty, rect.Height());
3365 if (!x.has_value() || !y.has_value() || !width.has_value() || !height.has_value()) {
3366 continue;
3367 }
3368 RectF responseRegion(
3369 rect.GetOffset().GetX() + x.value(), rect.GetOffset().GetY() + y.value(), width.value(), height.value());
3370 responseRegionList.emplace_back(responseRegion);
3371 }
3372 return responseRegionList;
3373 }
3374
GetResponseRegionListForRecognizer(int32_t sourceType)3375 std::vector<RectF> FrameNode::GetResponseRegionListForRecognizer(int32_t sourceType)
3376 {
3377 auto paintRect = renderContext_->GetPaintRectWithoutTransform();
3378 auto responseRegionList = GetResponseRegionList(paintRect, sourceType);
3379 return responseRegionList;
3380 }
3381
GetResponseRegionListForTouch(const RectF & windowRect)3382 std::vector<RectF> FrameNode::GetResponseRegionListForTouch(const RectF& windowRect)
3383 {
3384 ACE_LAYOUT_TRACE_BEGIN("GetResponseRegionListForTouch");
3385 std::vector<RectF> responseRegionList;
3386 auto gestureHub = eventHub_ ? eventHub_->GetGestureEventHub() : nullptr;
3387 if (!gestureHub) {
3388 ACE_LAYOUT_TRACE_END()
3389 return responseRegionList;
3390 }
3391 if (!renderContext_) {
3392 ACE_LAYOUT_TRACE_END()
3393 return responseRegionList;
3394 }
3395 bool isAccessibilityClickable = gestureHub->IsAccessibilityClickable();
3396 if (!isAccessibilityClickable) {
3397 ACE_LAYOUT_TRACE_END()
3398 return responseRegionList;
3399 }
3400 auto offset = GetPositionToScreenWithTransform();
3401 auto rect = renderContext_->GetPaintRectWithoutTransform();
3402 RectF rectToScreen{offset.GetX(), offset.GetY(), rect.Width(), rect.Height()};
3403 if (rectToScreen.Left() >= windowRect.Right() || rectToScreen.Right() <= windowRect.Left() ||
3404 rectToScreen.Top() >= windowRect.Bottom() || rectToScreen.Bottom() <= windowRect.Top()) {
3405 ACE_LAYOUT_TRACE_END()
3406 return responseRegionList;
3407 }
3408 if (gestureHub->GetResponseRegion().empty()) {
3409 RectF rectToScreen{round(offset.GetX()), round(offset.GetY()), round(rect.Width()), round(rect.Height())};
3410 responseRegionList.emplace_back(rectToScreen);
3411 ACE_LAYOUT_TRACE_END()
3412 return responseRegionList;
3413 }
3414
3415 auto scaleProperty = ScaleProperty::CreateScaleProperty();
3416 for (const auto& region : gestureHub->GetResponseRegion()) {
3417 auto x = ConvertToPx(region.GetOffset().GetX(), scaleProperty, rect.Width());
3418 auto y = ConvertToPx(region.GetOffset().GetY(), scaleProperty, rect.Height());
3419 auto width = ConvertToPx(region.GetWidth(), scaleProperty, rect.Width());
3420 auto height = ConvertToPx(region.GetHeight(), scaleProperty, rect.Height());
3421 if (!x.has_value() || !y.has_value() || !width.has_value() || !height.has_value()) {
3422 continue;
3423 }
3424 RectF responseRegion(round(offset.GetX() + x.value()), round(offset.GetY() + y.value()),
3425 round(width.value()), round(height.value()));
3426 responseRegionList.emplace_back(responseRegion);
3427 }
3428 ACE_LAYOUT_TRACE_END()
3429 return responseRegionList;
3430 }
3431
GetResponseRegionListByTraversal(std::vector<RectF> & responseRegionList,const RectF & windowRect)3432 void FrameNode::GetResponseRegionListByTraversal(std::vector<RectF>& responseRegionList, const RectF& windowRect)
3433 {
3434 auto rootRegionList = GetResponseRegionListForTouch(windowRect);
3435 if (!rootRegionList.empty()) {
3436 for (auto rect : rootRegionList) {
3437 responseRegionList.push_back(rect.IntersectRectT(windowRect));
3438 }
3439 return;
3440 }
3441 for (auto childWeak = frameChildren_.rbegin(); childWeak != frameChildren_.rend(); ++childWeak) {
3442 const auto& child = childWeak->Upgrade();
3443 if (!child) {
3444 continue;
3445 }
3446 child->GetResponseRegionListByTraversal(responseRegionList, windowRect);
3447 }
3448 }
3449
InResponseRegionList(const PointF & parentLocalPoint,const std::vector<RectF> & responseRegionList)3450 bool FrameNode::InResponseRegionList(const PointF& parentLocalPoint, const std::vector<RectF>& responseRegionList)
3451 {
3452 if (IsPaintRectWithTransformValid()) {
3453 return false;
3454 }
3455 for (const auto& rect : responseRegionList) {
3456 if (rect.IsInRegion(parentLocalPoint)) {
3457 return true;
3458 }
3459 }
3460 return false;
3461 }
3462
MouseTest(const PointF & globalPoint,const PointF & parentLocalPoint,MouseTestResult & onMouseResult,MouseTestResult & onHoverResult,RefPtr<FrameNode> & hoverNode)3463 HitTestResult FrameNode::MouseTest(const PointF& globalPoint, const PointF& parentLocalPoint,
3464 MouseTestResult& onMouseResult, MouseTestResult& onHoverResult, RefPtr<FrameNode>& hoverNode)
3465 {
3466 // unuseable function. do nothing.
3467 return HitTestResult::BUBBLING;
3468 }
3469
CheckChildHitTestResult(HitTestResult childHitResult,const RefPtr<OHOS::Ace::NG::FrameNode> & child,bool & preventBubbling,bool & consumed,bool isExclusiveEventForChild,bool & blockHierarchy)3470 bool CheckChildHitTestResult(HitTestResult childHitResult, const RefPtr<OHOS::Ace::NG::FrameNode>& child,
3471 bool& preventBubbling, bool& consumed, bool isExclusiveEventForChild, bool& blockHierarchy)
3472 {
3473 consumed = false;
3474 if (childHitResult == HitTestResult::STOP_BUBBLING) {
3475 preventBubbling = true;
3476 consumed = true;
3477 return ((child->GetHitTestMode() == HitTestMode::HTMBLOCK) ||
3478 (child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
3479 (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ||
3480 ((child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT) && isExclusiveEventForChild));
3481 }
3482 if (childHitResult == HitTestResult::BLOCK_HIERARCHY) {
3483 blockHierarchy = true;
3484 consumed = true;
3485 return true;
3486 }
3487 if (childHitResult == HitTestResult::BUBBLING) {
3488 consumed = true;
3489 return ((child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
3490 (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ||
3491 ((child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT &&
3492 child->GetHitTestMode() != HitTestMode::HTMBLOCK_DESCENDANTS) &&
3493 isExclusiveEventForChild));
3494 }
3495 return false;
3496 }
3497
HitTestChildren(const PointF & globalPoint,const PointF & localPoint,const PointF & subRevertPoint,TouchRestrict & touchRestrict,AxisTestResult & newComingTargets,bool & preventBubbling,bool & consumed,bool & blockHierarchy)3498 void FrameNode::HitTestChildren(const PointF& globalPoint, const PointF& localPoint,
3499 const PointF& subRevertPoint, TouchRestrict& touchRestrict, AxisTestResult& newComingTargets, bool& preventBubbling,
3500 bool& consumed, bool& blockHierarchy)
3501 {
3502 if (GetHitTestMode() == HitTestMode::HTMBLOCK || GetHitTestMode() == HitTestMode::HTMBLOCK_DESCENDANTS) {
3503 return;
3504 }
3505
3506 for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
3507 const auto& child = iter->Upgrade();
3508 if (!child) {
3509 continue;
3510 }
3511 auto childHitResult = child->AxisTest(globalPoint, localPoint, subRevertPoint, touchRestrict, newComingTargets);
3512 if (CheckChildHitTestResult(
3513 childHitResult, child, preventBubbling, consumed, IsExclusiveEventForChild(), blockHierarchy)) {
3514 return;
3515 }
3516 }
3517 }
3518
AxisTest(const PointF & globalPoint,const PointF & parentLocalPoint,const PointF & parentRevertPoint,TouchRestrict & touchRestrict,AxisTestResult & axisResult)3519 HitTestResult FrameNode::AxisTest(const PointF& globalPoint, const PointF& parentLocalPoint,
3520 const PointF& parentRevertPoint, TouchRestrict& touchRestrict, AxisTestResult& axisResult)
3521 {
3522 if (!isActive_ || (eventHub_ && !eventHub_->IsEnabled())) {
3523 TAG_LOGW(AceLogTag::ACE_UIEVENT, "%{public}s/%{public}d is inActive, needn't do touch test",
3524 tag_.c_str(), nodeId_);
3525 return HitTestResult::OUT_OF_REGION;
3526 }
3527 {
3528 ACE_DEBUG_SCOPED_TRACE("FrameNode::IsOutOfTouchTestRegion");
3529 if (IsOutOfTouchTestRegion(parentRevertPoint, touchRestrict.touchEvent)) {
3530 return HitTestResult::OUT_OF_REGION;
3531 }
3532 }
3533 HitTestResult testResult = HitTestResult::OUT_OF_REGION;
3534 bool preventBubbling = false;
3535 bool blockHierarchy = false;
3536 AxisTestResult newComingTargets;
3537 auto localPoint = parentLocalPoint - renderContext_->GetPaintRectWithTransform().GetOffset();
3538 renderContext_->GetPointWithTransform(localPoint);
3539 auto revertPoint = parentRevertPoint;
3540 MapPointTo(revertPoint, GetOrRefreshMatrixFromCache().revertMatrix);
3541 auto subRevertPoint = revertPoint - renderContext_->GetPaintRectWithoutTransform().GetOffset();
3542 bool consumed = false;
3543 HitTestChildren(globalPoint, localPoint, subRevertPoint, touchRestrict, newComingTargets, preventBubbling,
3544 consumed, blockHierarchy);
3545 CollectSelfAxisResult(globalPoint, localPoint, consumed, revertPoint, newComingTargets, preventBubbling, testResult,
3546 touchRestrict, blockHierarchy);
3547
3548 axisResult.splice(axisResult.end(), std::move(newComingTargets));
3549 if (!consumed) {
3550 return testResult;
3551 }
3552 if (testResult == HitTestResult::OUT_OF_REGION) {
3553 // consume only by self.
3554 if (preventBubbling) {
3555 return HitTestResult::STOP_BUBBLING;
3556 }
3557 return (GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ? HitTestResult::SELF_TRANSPARENT
3558 : HitTestResult::BUBBLING;
3559 }
3560 return testResult;
3561 }
3562
CollectSelfAxisResult(const PointF & globalPoint,const PointF & localPoint,bool & consumed,const PointF & parentRevertPoint,AxisTestResult & axisResult,bool & preventBubbling,HitTestResult & testResult,TouchRestrict & touchRestrict,bool blockHierarchy)3563 void FrameNode::CollectSelfAxisResult(const PointF& globalPoint, const PointF& localPoint, bool& consumed,
3564 const PointF& parentRevertPoint, AxisTestResult& axisResult, bool& preventBubbling, HitTestResult& testResult,
3565 TouchRestrict& touchRestrict, bool blockHierarchy)
3566 {
3567 if (consumed) {
3568 if (GetHitTestMode() == HitTestMode::HTMBLOCK_HIERARCHY) {
3569 testResult = HitTestResult::BLOCK_HIERARCHY;
3570 } else {
3571 if (blockHierarchy) {
3572 testResult = HitTestResult::BLOCK_HIERARCHY;
3573 } else {
3574 testResult = preventBubbling ? HitTestResult::STOP_BUBBLING : HitTestResult::BUBBLING;
3575 }
3576 }
3577 consumed = false;
3578 } else {
3579 if (GetHitTestMode() == HitTestMode::HTMBLOCK) {
3580 testResult = HitTestResult::STOP_BUBBLING;
3581 }
3582 if (GetHitTestMode() == HitTestMode::HTMBLOCK_HIERARCHY) {
3583 testResult = HitTestResult::BLOCK_HIERARCHY;
3584 }
3585 if (GetHitTestMode() == HitTestMode::HTMBLOCK_DESCENDANTS) {
3586 testResult = HitTestResult::BUBBLING;
3587 }
3588 }
3589 auto origRect = renderContext_->GetPaintRectWithoutTransform();
3590 auto resRegionList = GetResponseRegionList(origRect, static_cast<int32_t>(touchRestrict.touchEvent.sourceType));
3591 if (SystemProperties::GetDebugEnabled()) {
3592 TAG_LOGD(AceLogTag::ACE_UIEVENT, "AxisTest: point is %{public}s in %{public}s, depth: %{public}d",
3593 parentRevertPoint.ToString().c_str(), tag_.c_str(), depth_);
3594 for (const auto& rect : resRegionList) {
3595 TAG_LOGD(AceLogTag::ACE_UIEVENT, "AxisTest: resRegionList is %{public}s, point is %{public}s",
3596 rect.ToString().c_str(), parentRevertPoint.ToString().c_str());
3597 }
3598 }
3599 if (preventBubbling || blockHierarchy) {
3600 return;
3601 }
3602 if (GetHitTestMode() == HitTestMode::HTMNONE || GetHitTestMode() == HitTestMode::HTMBLOCK_DESCENDANTS) {
3603 return;
3604 }
3605 if (InResponseRegionList(parentRevertPoint, resRegionList)) {
3606 consumed = true;
3607 auto inputHub = eventHub_ ? eventHub_->GetInputEventHub() : nullptr;
3608 if (inputHub) {
3609 const auto coordinateOffset = globalPoint - localPoint;
3610 inputHub->ProcessAxisTestHit(coordinateOffset, axisResult);
3611 }
3612 }
3613 }
3614
AnimateHoverEffect(bool isHovered) const3615 void FrameNode::AnimateHoverEffect(bool isHovered) const
3616 {
3617 auto renderContext = GetRenderContext();
3618 if (!renderContext) {
3619 return;
3620 }
3621 HoverEffectType animationType = HoverEffectType::UNKNOWN;
3622 auto inputEventHub = eventHub_ ? eventHub_->GetInputEventHub() : nullptr;
3623 if (inputEventHub) {
3624 animationType = inputEventHub->GetHoverEffect();
3625 if (animationType == HoverEffectType::UNKNOWN || animationType == HoverEffectType::AUTO) {
3626 animationType = inputEventHub->GetHoverEffectAuto();
3627 }
3628 }
3629 if (animationType == HoverEffectType::SCALE) {
3630 renderContext->AnimateHoverEffectScale(isHovered);
3631 } else if (animationType == HoverEffectType::BOARD) {
3632 renderContext->AnimateHoverEffectBoard(isHovered);
3633 }
3634 }
3635
GetOrCreateFocusHub()3636 RefPtr<FocusHub> FrameNode::GetOrCreateFocusHub()
3637 {
3638 if (focusHub_) {
3639 return focusHub_;
3640 }
3641 if (!pattern_) {
3642 focusHub_ = MakeRefPtr<FocusHub>(WeakClaim(this));
3643 } else {
3644 auto focusPattern = pattern_->GetFocusPattern();
3645 focusHub_ = MakeRefPtr<FocusHub>(WeakClaim(this), focusPattern);
3646 }
3647 return focusHub_;
3648 }
3649
GetOrCreateDragDropRelatedConfigurations()3650 const RefPtr<DragDropRelatedConfigurations>& FrameNode::GetOrCreateDragDropRelatedConfigurations()
3651 {
3652 if (dragDropRelatedConfigurations_) {
3653 return dragDropRelatedConfigurations_;
3654 }
3655 dragDropRelatedConfigurations_ = MakeRefPtr<DragDropRelatedConfigurations>();
3656 return dragDropRelatedConfigurations_;
3657 }
3658
GetOrCreateFocusHub(FocusType type,bool focusable,FocusStyleType focusStyleType,const std::unique_ptr<FocusPaintParam> & paintParamsPtr)3659 const RefPtr<FocusHub>& FrameNode::GetOrCreateFocusHub(FocusType type, bool focusable, FocusStyleType focusStyleType,
3660 const std::unique_ptr<FocusPaintParam>& paintParamsPtr)
3661 {
3662 if (focusHub_) {
3663 return focusHub_;
3664 }
3665 focusHub_ = MakeRefPtr<FocusHub>(WeakClaim(this), type, focusable);
3666 focusHub_->SetFocusStyleType(focusStyleType);
3667 if (paintParamsPtr) {
3668 focusHub_->SetFocusPaintParamsPtr(paintParamsPtr);
3669 }
3670 return focusHub_;
3671 }
3672
GetOrCreateFocusHub(const FocusPattern & focusPattern)3673 const RefPtr<FocusHub>& FrameNode::GetOrCreateFocusHub(const FocusPattern& focusPattern)
3674 {
3675 if (focusHub_) {
3676 return focusHub_;
3677 }
3678 focusHub_ = MakeRefPtr<FocusHub>(WeakClaim(this), focusPattern);
3679 return focusHub_;
3680 }
3681
OnWindowShow()3682 void FrameNode::OnWindowShow()
3683 {
3684 pattern_->OnWindowShow();
3685 }
3686
OnWindowHide()3687 void FrameNode::OnWindowHide()
3688 {
3689 pattern_->OnWindowHide();
3690 }
3691
OnWindowFocused()3692 void FrameNode::OnWindowFocused()
3693 {
3694 if (renderContext_) {
3695 renderContext_->UpdateWindowFocusState(true);
3696 }
3697 pattern_->OnWindowFocused();
3698 }
3699
OnWindowUnfocused()3700 void FrameNode::OnWindowUnfocused()
3701 {
3702 if (renderContext_) {
3703 renderContext_->UpdateWindowFocusState(false);
3704 }
3705 pattern_->OnWindowUnfocused();
3706 }
3707
OnWindowActivated()3708 void FrameNode::OnWindowActivated()
3709 {
3710 if (renderContext_) {
3711 renderContext_->UpdateWindowActiveState(true);
3712 }
3713 pattern_->OnWindowActivated();
3714 }
3715
OnWindowDeactivated()3716 void FrameNode::OnWindowDeactivated()
3717 {
3718 if (renderContext_) {
3719 renderContext_->UpdateWindowActiveState(false);
3720 }
3721 pattern_->OnWindowDeactivated();
3722 }
3723
ContextPositionConvertToPX(const RefPtr<RenderContext> & context,const SizeF & percentReference)3724 std::pair<float, float> FrameNode::ContextPositionConvertToPX(
3725 const RefPtr<RenderContext>& context, const SizeF& percentReference)
3726 {
3727 std::pair<float, float> position;
3728 CHECK_NULL_RETURN(context, position);
3729 auto scaleProperty = ScaleProperty::CreateScaleProperty();
3730 position.first =
3731 ConvertToPx(context->GetPositionProperty()->GetPosition()->GetX(), scaleProperty, percentReference.Width())
3732 .value_or(0.0);
3733 position.second =
3734 ConvertToPx(context->GetPositionProperty()->GetPosition()->GetY(), scaleProperty, percentReference.Height())
3735 .value_or(0.0);
3736 return position;
3737 }
3738
OnPixelRoundFinish(const SizeF & pixelGridRoundSize)3739 void FrameNode::OnPixelRoundFinish(const SizeF& pixelGridRoundSize)
3740 {
3741 CHECK_NULL_VOID(pattern_);
3742 pattern_->OnPixelRoundFinish(pixelGridRoundSize);
3743 }
3744
OnWindowSizeChanged(int32_t width,int32_t height,WindowSizeChangeReason type)3745 void FrameNode::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
3746 {
3747 pattern_->OnWindowSizeChanged(width, height, type);
3748 }
3749
3750 /* @deprecated This func will be deleted, please use GetTransformRelativeOffset() instead. */
3751 // a node collect ancestor node position upto root node, if a node has "position" property
3752 // then node will use position value but not paint rect result value
GetOffsetRelativeToWindow() const3753 OffsetF FrameNode::GetOffsetRelativeToWindow() const
3754 {
3755 auto offset = geometryNode_->GetFrameOffset();
3756 auto parent = GetAncestorNodeOfFrame(true);
3757 if (renderContext_ && renderContext_->GetPositionProperty()) {
3758 if (renderContext_->GetPositionProperty()->HasPosition()) {
3759 auto renderPosition =
3760 ContextPositionConvertToPX(renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
3761 offset.SetX(static_cast<float>(renderPosition.first));
3762 offset.SetY(static_cast<float>(renderPosition.second));
3763 }
3764 }
3765 while (parent) {
3766 auto parentRenderContext = parent->GetRenderContext();
3767 if (parentRenderContext && parentRenderContext->GetPositionProperty()) {
3768 if (parentRenderContext->GetPositionProperty()->HasPosition()) {
3769 auto parentLayoutProperty = parent->GetLayoutProperty();
3770 CHECK_NULL_RETURN(parentLayoutProperty, offset);
3771 auto parentRenderContextPosition = ContextPositionConvertToPX(
3772 parentRenderContext, parentLayoutProperty->GetLayoutConstraint()->percentReference);
3773 offset.AddX(static_cast<float>(parentRenderContextPosition.first));
3774 offset.AddY(static_cast<float>(parentRenderContextPosition.second));
3775 parent = parent->GetAncestorNodeOfFrame(true);
3776 continue;
3777 }
3778 }
3779 if (parentRenderContext) {
3780 offset += parentRenderContext->GetPaintRectWithoutTransform().GetOffset();
3781 }
3782 parent = parent->GetAncestorNodeOfFrame(true);
3783 }
3784
3785 return offset;
3786 }
3787
3788 // returns a node's collected offset(see GetOffsetRelativeToWindow)
3789 // with offset of window to screen
3790 // ex. textInput component wrap offset relative to screen into a config and send to ime framework
GetPositionToScreen()3791 OffsetF FrameNode::GetPositionToScreen()
3792 {
3793 auto pipelineContext = GetContext();
3794 CHECK_NULL_RETURN(pipelineContext, OffsetF());
3795 auto offsetCurrent = GetFinalOffsetRelativeToWindow(pipelineContext);
3796 auto windowOffset = pipelineContext->GetCurrentWindowRect().GetOffset();
3797 OffsetF offset(windowOffset.GetX() + offsetCurrent.GetX(), windowOffset.GetY() + offsetCurrent.GetY());
3798 return offset;
3799 }
3800
3801 // returns a node's collected offset(see GetOffsetRelativeToWindow)
3802 // with offset of window to globalDisplay
3803 // ex. textInput component wrap offset relative to globalDisplay into a config and send to ime framework
GetGlobalPositionOnDisplay() const3804 OffsetF FrameNode::GetGlobalPositionOnDisplay() const
3805 {
3806 auto pipelineContext = GetContext();
3807 CHECK_NULL_RETURN(pipelineContext, OffsetF());
3808 auto offsetCurrent = GetFinalOffsetRelativeToWindow(pipelineContext);
3809 auto globalDisplayWindowOffset = pipelineContext->GetGlobalDisplayWindowRect().GetOffset();
3810 OffsetF offset(globalDisplayWindowOffset.GetX() + offsetCurrent.GetX(),
3811 globalDisplayWindowOffset.GetY() + offsetCurrent.GetY());
3812 return offset;
3813 }
3814
GetFinalOffsetRelativeToWindow(PipelineContext * pipelineContext) const3815 OffsetF FrameNode::GetFinalOffsetRelativeToWindow(PipelineContext* pipelineContext) const
3816 {
3817 auto offsetCurrent = GetOffsetRelativeToWindow();
3818 auto windowManager = pipelineContext->GetWindowManager();
3819 auto container = Container::CurrentSafely();
3820 if (container && windowManager && windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING) {
3821 auto windowScale = container->GetWindowScale();
3822 offsetCurrent = offsetCurrent * windowScale;
3823 }
3824 return offsetCurrent;
3825 }
3826
3827 // returns a node's offset relative to parent and consider graphic transform rotate properties
GetPositionToParentWithTransform() const3828 OffsetF FrameNode::GetPositionToParentWithTransform() const
3829 {
3830 auto context = GetRenderContext();
3831 CHECK_NULL_RETURN(context, OffsetF());
3832 auto offset = context->GetPaintRectWithoutTransform().GetOffset();
3833 PointF pointTmp(offset.GetX(), offset.GetY());
3834 context->GetPointTransformRotate(pointTmp);
3835 offset.SetX(pointTmp.GetX());
3836 offset.SetY(pointTmp.GetY());
3837 return offset;
3838 }
3839
3840 // returns a node's offset collected offset(see GetPositionToWindowWithTransform)
3841 // then plus window's offset relative to screen
GetPositionToScreenWithTransform()3842 OffsetF FrameNode::GetPositionToScreenWithTransform()
3843 {
3844 auto pipelineContext = GetContext();
3845 CHECK_NULL_RETURN(pipelineContext, OffsetF());
3846 auto windowOffset = pipelineContext->GetCurrentWindowRect().GetOffset();
3847 OffsetF nodeOffset = GetPositionToWindowWithTransform();
3848 auto windowManager = pipelineContext->GetWindowManager();
3849 auto container = Container::CurrentSafely();
3850 if (container && windowManager && windowManager->GetWindowMode() == WindowMode::WINDOW_MODE_FLOATING) {
3851 auto windowScale = container->GetWindowScale();
3852 nodeOffset = nodeOffset * windowScale;
3853 }
3854 OffsetF offset(windowOffset.GetX() + nodeOffset.GetX(), windowOffset.GetY() + nodeOffset.GetY());
3855 return offset;
3856 }
3857
3858 // returns a node's offset relative to window
3859 // and consider every ancestor node's graphic transform rotate properties
3860 // ancestor will check boundary of window scene(exclude)
GetPositionToWindowWithTransform(bool fromBottom) const3861 OffsetF FrameNode::GetPositionToWindowWithTransform(bool fromBottom) const
3862 {
3863 auto context = GetRenderContext();
3864 CHECK_NULL_RETURN(context, OffsetF());
3865 auto rect = context->GetPaintRectWithoutTransform();
3866 OffsetF offset;
3867 if (!fromBottom) {
3868 offset = rect.GetOffset();
3869 } else {
3870 OffsetF offsetBottom(rect.GetX() + rect.Width(), rect.GetY() + rect.Height());
3871 offset = offsetBottom;
3872 }
3873
3874 PointF pointNode(offset.GetX(), offset.GetY());
3875 context->GetPointTransformRotate(pointNode);
3876 auto parent = GetAncestorNodeOfFrame(true);
3877 while (parent) {
3878 auto parentRenderContext = parent->GetRenderContext();
3879 offset = parentRenderContext->GetPaintRectWithoutTransform().GetOffset();
3880 PointF pointTmp(offset.GetX() + pointNode.GetX(), offset.GetY() + pointNode.GetY());
3881 parentRenderContext->GetPointTransformRotate(pointTmp);
3882 pointNode.SetX(pointTmp.GetX());
3883 pointNode.SetY(pointTmp.GetY());
3884 parent = parent->GetAncestorNodeOfFrame(true);
3885 }
3886 offset.SetX(pointNode.GetX());
3887 offset.SetY(pointNode.GetY());
3888 return offset;
3889 }
3890
GetTransformScaleRelativeToWindow() const3891 VectorF FrameNode::GetTransformScaleRelativeToWindow() const
3892 {
3893 VectorF finalScale {1.0f, 1.0f};
3894 auto context = GetRenderContext();
3895 if (context) {
3896 auto scale = GetTransformScale();
3897 finalScale.x = scale.x;
3898 finalScale.y = scale.y;
3899 }
3900
3901 auto parent = GetAncestorNodeOfFrame(true);
3902 while (parent) {
3903 auto contextParent = parent->GetRenderContext();
3904 if (contextParent) {
3905 auto scale = parent->GetTransformScale();
3906 finalScale.x *= scale.x;
3907 finalScale.y *= scale.y;
3908 }
3909 parent = parent->GetAncestorNodeOfFrame(true);
3910 }
3911 return finalScale;
3912 }
3913
3914 // returns a node's rect relative to window
3915 // and accumulate every ancestor node's graphic properties such as rotate and transform
3916 // detail graphic properites see RosenRenderContext::GetPaintRectWithTransform
3917 // ancestor will check boundary of window scene(exclude)
GetTransformRectRelativeToWindow(bool checkBoundary) const3918 RectF FrameNode::GetTransformRectRelativeToWindow(bool checkBoundary) const
3919 {
3920 auto context = GetRenderContext();
3921 CHECK_NULL_RETURN(context, RectF());
3922 RectF rect = context->GetPaintRectWithTransform();
3923 auto parent = GetAncestorNodeOfFrame(true);
3924 while (parent) {
3925 if (checkBoundary && parent->IsWindowBoundary()) {
3926 break;
3927 }
3928 rect = ApplyFrameNodeTranformToRect(rect, parent);
3929 parent = parent->GetAncestorNodeOfFrame(true);
3930 }
3931 return rect;
3932 }
3933
3934 // returns a node's offset relative to window
3935 // and accumulate every ancestor node's graphic properties such as rotate and transform
3936 // detail graphic properites see RosenRenderContext::GetPaintRectWithTransform
3937 // ancestor will check boundary of window scene(exclude)
GetTransformRelativeOffset() const3938 OffsetF FrameNode::GetTransformRelativeOffset() const
3939 {
3940 auto context = GetRenderContext();
3941 CHECK_NULL_RETURN(context, OffsetF());
3942 auto offset = context->GetPaintRectWithTransform().GetOffset();
3943 auto parent = GetAncestorNodeOfFrame(true);
3944
3945 while (parent) {
3946 auto parentRenderContext = parent->GetRenderContext();
3947 offset += parentRenderContext->GetPaintRectWithTransform().GetOffset();
3948 parent = parent->GetAncestorNodeOfFrame(true);
3949 }
3950
3951 return offset;
3952 }
3953
GetPaintRectOffset(bool excludeSelf,bool checkBoundary,bool checkScreen) const3954 OffsetF FrameNode::GetPaintRectOffset(bool excludeSelf, bool checkBoundary, bool checkScreen) const
3955 {
3956 auto context = GetRenderContext();
3957 CHECK_NULL_RETURN(context, OffsetF());
3958 OffsetF offset = excludeSelf ? OffsetF() : context->GetPaintRectWithTransform().GetOffset();
3959 auto parent = GetAncestorNodeOfFrame(checkBoundary);
3960 while (parent) {
3961 if ((!checkBoundary && parent->CheckTopWindowBoundary()) ||
3962 (checkScreen && parent->CheckTopScreen())) {
3963 break;
3964 }
3965 auto renderContext = parent->GetRenderContext();
3966 CHECK_NULL_RETURN(renderContext, OffsetF());
3967 offset += renderContext->GetPaintRectWithTransform().GetOffset();
3968 parent = parent->GetAncestorNodeOfFrame(checkBoundary);
3969 }
3970 return offset;
3971 }
3972
GetPaintRectOffsetNG(bool excludeSelf,bool checkBoundary) const3973 OffsetF FrameNode::GetPaintRectOffsetNG(bool excludeSelf, bool checkBoundary) const
3974 {
3975 auto context = GetRenderContext();
3976 CHECK_NULL_RETURN(context, OffsetF());
3977 OffsetF offset = excludeSelf ? OffsetF() : context->GetPaintRectWithoutTransform().GetOffset();
3978 Point point = Matrix4::Invert(context->GetRevertMatrix()) * Point(offset.GetX(), offset.GetY());
3979 auto parent = GetAncestorNodeOfFrame(checkBoundary);
3980 while (parent) {
3981 if (!checkBoundary && parent->CheckTopWindowBoundary()) {
3982 break;
3983 }
3984 auto renderContext = parent->GetRenderContext();
3985 CHECK_NULL_RETURN(renderContext, OffsetF());
3986 auto parentOffset = renderContext->GetPaintRectWithoutTransform().GetOffset();
3987 point = point + Offset(parentOffset.GetX(), parentOffset.GetY());
3988 auto parentMatrix = Matrix4::Invert(renderContext->GetRevertMatrix());
3989 point = parentMatrix * point;
3990 parent = parent->GetAncestorNodeOfFrame(checkBoundary);
3991 }
3992 return OffsetF(point.GetX(), point.GetY());
3993 }
3994
GetRectPoints(SizeF & frameSize)3995 std::vector<Point> GetRectPoints(SizeF& frameSize)
3996 {
3997 std::vector<Point> pointList;
3998 pointList.push_back(Point(0, 0));
3999 pointList.push_back(Point(frameSize.Width(), 0));
4000 pointList.push_back(Point(0, frameSize.Height()));
4001 pointList.push_back(Point(frameSize.Width(), frameSize.Height()));
4002 return pointList;
4003 }
4004
GetBoundingBox(std::vector<Point> & pointList)4005 RectF GetBoundingBox(std::vector<Point>& pointList)
4006 {
4007 Point pMax = pointList[0];
4008 Point pMin = pointList[0];
4009
4010 for (auto &point: pointList) {
4011 if (point.GetX() > pMax.GetX()) {
4012 pMax.SetX(point.GetX());
4013 }
4014 if (point.GetX() < pMin.GetX()) {
4015 pMin.SetX(point.GetX());
4016 }
4017 if (point.GetY() > pMax.GetY()) {
4018 pMax.SetY(point.GetY());
4019 }
4020 if (point.GetY() < pMin.GetY()) {
4021 pMin.SetY(point.GetY());
4022 }
4023 }
4024 return RectF(pMin.GetX(), pMin.GetY(), pMax.GetX() - pMin.GetX(), pMax.GetY() - pMin.GetY());
4025 }
4026
4027 // returns node offset relate to parent and consider transform matrix of parent
GetRectPointToParentWithTransform(std::vector<Point> & pointList,const RefPtr<FrameNode> & parent) const4028 bool FrameNode::GetRectPointToParentWithTransform(std::vector<Point>& pointList, const RefPtr<FrameNode>& parent) const
4029 {
4030 auto renderContext = parent->GetRenderContext();
4031 CHECK_NULL_RETURN(renderContext, false);
4032 auto parentOffset = renderContext->GetPaintRectWithoutTransform().GetOffset();
4033 auto parentMatrix = Matrix4::Invert(renderContext->GetRevertMatrix());
4034 for (auto& point: pointList) {
4035 point = point + Offset(parentOffset.GetX(), parentOffset.GetY());
4036 point = parentMatrix * point;
4037 }
4038 return true;
4039 }
4040
4041 // returns node accumulated offset upto an ancestor has no renderContext or window
4042 // and consider each ancestor's transform matrix
GetPaintRectToWindowWithTransform()4043 RectF FrameNode::GetPaintRectToWindowWithTransform()
4044 {
4045 auto context = GetRenderContext();
4046 CHECK_NULL_RETURN(context, RectF());
4047 auto geometryNode = GetGeometryNode();
4048 CHECK_NULL_RETURN(geometryNode, RectF());
4049 auto frameSize = geometryNode->GetFrameSize();
4050 auto pointList = GetRectPoints(frameSize);
4051 GetRectPointToParentWithTransform(pointList, Claim(this));
4052 auto parent = GetAncestorNodeOfFrame(true);
4053 while (parent) {
4054 if (GetRectPointToParentWithTransform(pointList, parent)) {
4055 parent = parent->GetAncestorNodeOfFrame(true);
4056 } else {
4057 return RectF();
4058 }
4059 }
4060 return GetBoundingBox(pointList);
4061 }
4062
4063 // returns a node's geometry offset relative to window
4064 // used when a node is in the process of layout
4065 // because offset during layout is NOT synced to renderContext yet
GetParentGlobalOffsetDuringLayout() const4066 OffsetF FrameNode::GetParentGlobalOffsetDuringLayout() const
4067 {
4068 OffsetF offset {};
4069 auto parent = GetAncestorNodeOfFrame(true);
4070 while (parent) {
4071 offset += parent->geometryNode_->GetFrameOffset();
4072 parent = parent->GetAncestorNodeOfFrame(true);
4073 }
4074 return offset;
4075 }
4076
4077 // returns a node's offset relative to window
4078 // and accumulate every ancestor node's graphic translate properties
4079 // error means any ancestor node renderContext has hasScales_ bool
GetPaintRectGlobalOffsetWithTranslate(bool excludeSelf,bool checkBoundary) const4080 std::pair<OffsetF, bool> FrameNode::GetPaintRectGlobalOffsetWithTranslate(bool excludeSelf, bool checkBoundary) const
4081 {
4082 bool error = false;
4083 auto context = GetRenderContext();
4084 CHECK_NULL_RETURN(context, std::make_pair(OffsetF(), error));
4085 OffsetF offset = excludeSelf ? OffsetF() : context->GetPaintRectWithTranslate().first.GetOffset();
4086 auto parent = GetAncestorNodeOfFrame(checkBoundary);
4087 while (parent) {
4088 auto renderContext = parent->GetRenderContext();
4089 CHECK_NULL_RETURN(renderContext, std::make_pair(OffsetF(), error));
4090 auto [rect, err] = renderContext->GetPaintRectWithTranslate();
4091 error = error || err;
4092 CHECK_NULL_RETURN(rect.IsValid(), std::make_pair(offset + parent->GetPaintRectOffset(), error));
4093 offset += rect.GetOffset();
4094 parent = parent->GetAncestorNodeOfFrame(checkBoundary);
4095 }
4096 return std::make_pair(offset, error);
4097 }
4098
4099 // returns a node's offset relative to page node
4100 // and accumulate every ancestor node's graphic properties such as rotate and transform
4101 // most of applications has page offset of status bar height
GetPaintRectOffsetToPage() const4102 OffsetF FrameNode::GetPaintRectOffsetToPage() const
4103 {
4104 auto context = GetRenderContext();
4105 CHECK_NULL_RETURN(context, OffsetF());
4106 OffsetF offset = context->GetPaintRectWithTransform().GetOffset();
4107 auto parent = GetAncestorNodeOfFrame(true);
4108 while (parent && parent->GetTag() != V2::PAGE_ETS_TAG) {
4109 auto renderContext = parent->GetRenderContext();
4110 CHECK_NULL_RETURN(renderContext, OffsetF());
4111 // Eliminate the impact of default page transition
4112 offset += renderContext->GetPaintRectWithTransform().GetOffset();
4113 parent = parent->GetAncestorNodeOfFrame(true);
4114 }
4115 return (parent && parent->GetTag() == V2::PAGE_ETS_TAG) ? offset : OffsetF();
4116 }
4117
GetViewPort(bool checkBoundary) const4118 std::optional<RectF> FrameNode::GetViewPort(bool checkBoundary) const
4119 {
4120 if (viewPort_.has_value()) {
4121 return viewPort_;
4122 }
4123 auto parent = GetAncestorNodeOfFrame(checkBoundary);
4124 while (parent && parent->GetTag() != V2::PAGE_ETS_TAG) {
4125 auto parentViewPort = parent->GetSelfViewPort();
4126 if (parentViewPort.has_value()) {
4127 return parentViewPort;
4128 }
4129 parent = parent->GetAncestorNodeOfFrame(checkBoundary);
4130 }
4131 return std::nullopt;
4132 }
4133
OnNotifyMemoryLevel(int32_t level)4134 void FrameNode::OnNotifyMemoryLevel(int32_t level)
4135 {
4136 pattern_->OnNotifyMemoryLevel(level);
4137 }
4138
GetAllDepthChildrenCount()4139 int32_t FrameNode::GetAllDepthChildrenCount()
4140 {
4141 int32_t result = 0;
4142 std::list<RefPtr<FrameNode>> children;
4143 children.emplace_back(Claim(this));
4144 while (!children.empty()) {
4145 auto& node = children.front();
4146 if (!node->IsInternal()) {
4147 result++;
4148 node->GenerateOneDepthVisibleFrame(children);
4149 }
4150 children.pop_front();
4151 }
4152 return result;
4153 }
4154
OnAccessibilityEvent(AccessibilityEventType eventType,WindowsContentChangeTypes windowsContentChangeType) const4155 void FrameNode::OnAccessibilityEvent(
4156 AccessibilityEventType eventType, WindowsContentChangeTypes windowsContentChangeType) const
4157 {
4158 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
4159 AccessibilityEvent event;
4160 event.type = eventType;
4161 event.windowContentChangeTypes = windowsContentChangeType;
4162 event.nodeId = accessibilityId_;
4163 auto pipeline = GetContext();
4164 CHECK_NULL_VOID(pipeline);
4165 pipeline->SendEventToAccessibility(event);
4166 }
4167 }
4168
OnAccessibilityEventForVirtualNode(AccessibilityEventType eventType,int64_t accessibilityId)4169 void FrameNode::OnAccessibilityEventForVirtualNode(AccessibilityEventType eventType, int64_t accessibilityId)
4170 {
4171 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
4172 AccessibilityEvent event;
4173 event.type = eventType;
4174 event.windowContentChangeTypes = WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID;
4175 event.nodeId = accessibilityId;
4176 auto pipeline = GetContext();
4177 CHECK_NULL_VOID(pipeline);
4178 pipeline->SendEventToAccessibility(event);
4179 }
4180 }
4181
OnAccessibilityEvent(AccessibilityEventType eventType,int32_t startIndex,int32_t endIndex)4182 void FrameNode::OnAccessibilityEvent(
4183 AccessibilityEventType eventType, int32_t startIndex, int32_t endIndex)
4184 {
4185 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
4186 AccessibilityEvent event;
4187 event.type = eventType;
4188 event.nodeId = accessibilityId_;
4189 event.startIndex = startIndex;
4190 event.endIndex = endIndex;
4191 auto pipeline = GetContext();
4192 CHECK_NULL_VOID(pipeline);
4193 pipeline->SendEventToAccessibilityWithNode(event, Claim(this));
4194 }
4195 }
4196
OnAccessibilityEvent(AccessibilityEventType eventType,const std::string & beforeText,const std::string & latestContent)4197 void FrameNode::OnAccessibilityEvent(
4198 AccessibilityEventType eventType, const std::string& beforeText, const std::string& latestContent)
4199 {
4200 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
4201 AccessibilityEvent event;
4202 event.type = eventType;
4203 event.nodeId = accessibilityId_;
4204 event.beforeText = beforeText;
4205 event.latestContent = latestContent;
4206 auto pipeline = GetContext();
4207 CHECK_NULL_VOID(pipeline);
4208 pipeline->SendEventToAccessibilityWithNode(event, Claim(this));
4209 }
4210 }
4211
OnAccessibilityEvent(AccessibilityEventType eventType,int64_t stackNodeId,WindowsContentChangeTypes windowsContentChangeType)4212 void FrameNode::OnAccessibilityEvent(
4213 AccessibilityEventType eventType, int64_t stackNodeId, WindowsContentChangeTypes windowsContentChangeType)
4214 {
4215 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
4216 AccessibilityEvent event;
4217 event.type = eventType;
4218 event.windowContentChangeTypes = windowsContentChangeType;
4219 event.nodeId = accessibilityId_;
4220 event.stackNodeId = stackNodeId;
4221 auto pipeline = GetContext();
4222 CHECK_NULL_VOID(pipeline);
4223 pipeline->SendEventToAccessibility(event);
4224 }
4225 }
4226
OnAccessibilityEvent(AccessibilityEventType eventType,const std::string & textAnnouncedForAccessibility)4227 void FrameNode::OnAccessibilityEvent(
4228 AccessibilityEventType eventType, const std::string& textAnnouncedForAccessibility)
4229 {
4230 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
4231 if (eventType != AccessibilityEventType::ANNOUNCE_FOR_ACCESSIBILITY) {
4232 return;
4233 }
4234 AccessibilityEvent event;
4235 event.type = eventType;
4236 event.nodeId = accessibilityId_;
4237 event.textAnnouncedForAccessibility = textAnnouncedForAccessibility;
4238 auto pipeline = GetContext();
4239 CHECK_NULL_VOID(pipeline);
4240 pipeline->SendEventToAccessibilityWithNode(event, Claim(this));
4241 }
4242 }
4243
OnRecycle()4244 void FrameNode::OnRecycle()
4245 {
4246 for (const auto& destroyCallback : destroyCallbacksMap_) {
4247 if (destroyCallback.second) {
4248 destroyCallback.second();
4249 }
4250 }
4251 layoutProperty_->ResetGeometryTransition();
4252 pattern_->OnRecycle();
4253 UINode::OnRecycle();
4254
4255 auto accessibilityProperty = GetAccessibilityProperty<NG::AccessibilityProperty>();
4256 auto renderContext = GetRenderContext();
4257 ClearAccessibilityFocus(accessibilityProperty, renderContext);
4258 }
4259
OnReuse()4260 void FrameNode::OnReuse()
4261 {
4262 pattern_->OnReuse();
4263 UINode::OnReuse();
4264 if (SystemProperties::GetDeveloperModeOn()) {
4265 PaintDebugBoundary(SystemProperties::GetDebugBoundaryEnabled());
4266 }
4267 }
4268
MarkRemoving()4269 bool FrameNode::MarkRemoving()
4270 {
4271 bool pendingRemove = false;
4272 if (!layoutProperty_ || !geometryNode_) {
4273 return pendingRemove;
4274 }
4275
4276 isRemoving_ = true;
4277
4278 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
4279 if (geometryTransition != nullptr) {
4280 geometryTransition->Build(WeakClaim(this), false);
4281 pendingRemove = true;
4282 }
4283
4284 const auto children = GetChildren();
4285 for (const auto& child : children) {
4286 pendingRemove = child->MarkRemoving() || pendingRemove;
4287 }
4288 return pendingRemove;
4289 }
4290
AddHotZoneRect(const DimensionRect & hotZoneRect)4291 void FrameNode::AddHotZoneRect(const DimensionRect& hotZoneRect)
4292 {
4293 auto gestureHub = GetOrCreateGestureEventHub();
4294 gestureHub->AddResponseRect(hotZoneRect);
4295 }
4296
RemoveLastHotZoneRect() const4297 void FrameNode::RemoveLastHotZoneRect() const
4298 {
4299 auto gestureHub = eventHub_ ? eventHub_->GetOrCreateGestureEventHub() : nullptr;
4300 gestureHub->RemoveLastResponseRect();
4301 }
4302
OnRemoveFromParent(bool allowTransition)4303 bool FrameNode::OnRemoveFromParent(bool allowTransition)
4304 {
4305 // the node set isInDestroying state when destroying in pop animation
4306 // when in isInDestroying state node should not DetachFromMainTree preventing pop page from being white
4307 if (IsDestroyingState() && GetContext() && !GetContext()->IsDestroyed()) {
4308 return false;
4309 }
4310 // kick out transition animation if needed, wont re-entry if already detached.
4311 DetachFromMainTree(!allowTransition);
4312 auto context = GetRenderContext();
4313 CHECK_NULL_RETURN(context, false);
4314 if (!allowTransition || RemoveImmediately()) {
4315 // directly remove, reset parent and depth
4316 ResetParent();
4317 return true;
4318 }
4319 // delayed remove, will move self into disappearing children
4320 return false;
4321 }
4322
FindChildByPosition(float x,float y)4323 RefPtr<FrameNode> FrameNode::FindChildByPosition(float x, float y)
4324 {
4325 std::map<int32_t, RefPtr<FrameNode>> hitFrameNodes;
4326 std::list<RefPtr<FrameNode>> children;
4327 GenerateOneDepthAllFrame(children);
4328 for (const auto& child : children) {
4329 if (!child->IsActive()) {
4330 continue;
4331 }
4332 auto geometryNode = child->GetGeometryNode();
4333 if (!geometryNode) {
4334 continue;
4335 }
4336
4337 auto globalFrameRect = geometryNode->GetFrameRect();
4338 globalFrameRect.SetOffset(child->GetOffsetRelativeToWindow());
4339
4340 if (globalFrameRect.IsInRegion(PointF(x, y))) {
4341 hitFrameNodes.insert(std::make_pair(child->GetDepth(), child));
4342 }
4343 }
4344
4345 if (hitFrameNodes.empty()) {
4346 return nullptr;
4347 }
4348
4349 return hitFrameNodes.rbegin()->second;
4350 }
4351
FindChildByPositionWithoutChildTransform(float x,float y)4352 RefPtr<FrameNode> FrameNode::FindChildByPositionWithoutChildTransform(float x, float y)
4353 {
4354 std::map<int32_t, RefPtr<FrameNode>> hitFrameNodes;
4355 std::list<RefPtr<FrameNode>> children;
4356 GenerateOneDepthAllFrame(children);
4357 auto parentOffset = GetPositionToWindowWithTransform();
4358 for (const auto& child : children) {
4359 if (!child->IsActive()) {
4360 continue;
4361 }
4362 auto geometryNode = child->GetGeometryNode();
4363 if (!geometryNode) {
4364 continue;
4365 }
4366
4367 auto globalFrameRect = geometryNode->GetFrameRect();
4368 auto childOffset = geometryNode->GetFrameOffset();
4369 childOffset += parentOffset;
4370 globalFrameRect.SetOffset(childOffset);
4371
4372 if (globalFrameRect.IsInRegion(PointF(x, y))) {
4373 hitFrameNodes.insert(std::make_pair(child->GetDepth(), child));
4374 }
4375 }
4376
4377 if (hitFrameNodes.empty()) {
4378 return nullptr;
4379 }
4380
4381 return hitFrameNodes.rbegin()->second;
4382 }
4383
GetAnimatablePropertyFloat(const std::string & propertyName) const4384 RefPtr<NodeAnimatablePropertyBase> FrameNode::GetAnimatablePropertyFloat(const std::string& propertyName) const
4385 {
4386 auto iter = nodeAnimatablePropertyMap_.find(propertyName);
4387 if (iter == nodeAnimatablePropertyMap_.end()) {
4388 return nullptr;
4389 }
4390 return iter->second;
4391 }
4392
FindChildByName(const RefPtr<FrameNode> & parentNode,const std::string & nodeName)4393 RefPtr<FrameNode> FrameNode::FindChildByName(const RefPtr<FrameNode>& parentNode, const std::string& nodeName)
4394 {
4395 CHECK_NULL_RETURN(parentNode, nullptr);
4396 const auto& children = parentNode->GetChildren();
4397 for (const auto& child : children) {
4398 auto childFrameNode = AceType::DynamicCast<FrameNode>(child);
4399 if (childFrameNode && childFrameNode->GetInspectorId().value_or("") == nodeName) {
4400 return childFrameNode;
4401 }
4402 auto childFindResult = FindChildByName(childFrameNode, nodeName);
4403 if (childFindResult) {
4404 return childFindResult;
4405 }
4406 }
4407 return nullptr;
4408 }
4409
CreateAnimatablePropertyFloat(const std::string & propertyName,float value,const std::function<void (float)> & onCallbackEvent,const PropertyUnit & propertyType)4410 void FrameNode::CreateAnimatablePropertyFloat(const std::string& propertyName, float value,
4411 const std::function<void(float)>& onCallbackEvent, const PropertyUnit& propertyType)
4412 {
4413 auto context = GetRenderContext();
4414 CHECK_NULL_VOID(context);
4415 auto iter = nodeAnimatablePropertyMap_.find(propertyName);
4416 if (iter != nodeAnimatablePropertyMap_.end()) {
4417 return;
4418 }
4419 auto property = AceType::MakeRefPtr<NodeAnimatablePropertyFloat>(value, std::move(onCallbackEvent));
4420 context->AttachNodeAnimatableProperty(property);
4421 if (propertyType == PropertyUnit::PIXEL_POSITION) {
4422 property->SetPropertyUnit(propertyType);
4423 }
4424 nodeAnimatablePropertyMap_.emplace(propertyName, property);
4425 }
4426
DeleteAnimatablePropertyFloat(const std::string & propertyName)4427 void FrameNode::DeleteAnimatablePropertyFloat(const std::string& propertyName)
4428 {
4429 auto context = GetRenderContext();
4430 CHECK_NULL_VOID(context);
4431 RefPtr<NodeAnimatablePropertyBase> propertyRef = GetAnimatablePropertyFloat(propertyName);
4432 if (propertyRef) {
4433 context->DetachNodeAnimatableProperty(propertyRef);
4434 nodeAnimatablePropertyMap_.erase(propertyName);
4435 }
4436 }
4437
UpdateAnimatablePropertyFloat(const std::string & propertyName,float value)4438 void FrameNode::UpdateAnimatablePropertyFloat(const std::string& propertyName, float value)
4439 {
4440 auto iter = nodeAnimatablePropertyMap_.find(propertyName);
4441 if (iter == nodeAnimatablePropertyMap_.end()) {
4442 return;
4443 }
4444 auto property = AceType::DynamicCast<NodeAnimatablePropertyFloat>(iter->second);
4445 CHECK_NULL_VOID(property);
4446 property->Set(value);
4447 if (AnimationUtils::IsImplicitAnimationOpen()) {
4448 AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_START_ANIMATION);
4449 }
4450 }
4451
CreateAnimatableArithmeticProperty(const std::string & propertyName,RefPtr<CustomAnimatableArithmetic> & value,std::function<void (const RefPtr<CustomAnimatableArithmetic> &)> & onCallbackEvent)4452 void FrameNode::CreateAnimatableArithmeticProperty(const std::string& propertyName,
4453 RefPtr<CustomAnimatableArithmetic>& value,
4454 std::function<void(const RefPtr<CustomAnimatableArithmetic>&)>& onCallbackEvent)
4455 {
4456 auto context = GetRenderContext();
4457 CHECK_NULL_VOID(context);
4458 auto iter = nodeAnimatablePropertyMap_.find(propertyName);
4459 if (iter != nodeAnimatablePropertyMap_.end()) {
4460 return;
4461 }
4462 auto property = AceType::MakeRefPtr<NodeAnimatableArithmeticProperty>(value, std::move(onCallbackEvent));
4463 context->AttachNodeAnimatableProperty(property);
4464 nodeAnimatablePropertyMap_.emplace(propertyName, property);
4465 }
4466
UpdateAnimatableArithmeticProperty(const std::string & propertyName,RefPtr<CustomAnimatableArithmetic> & value)4467 void FrameNode::UpdateAnimatableArithmeticProperty(
4468 const std::string& propertyName, RefPtr<CustomAnimatableArithmetic>& value)
4469 {
4470 auto iter = nodeAnimatablePropertyMap_.find(propertyName);
4471 if (iter == nodeAnimatablePropertyMap_.end()) {
4472 return;
4473 }
4474 auto property = AceType::DynamicCast<NodeAnimatableArithmeticProperty>(iter->second);
4475 CHECK_NULL_VOID(property);
4476 property->Set(value);
4477 }
4478
ProvideRestoreInfo()4479 std::string FrameNode::ProvideRestoreInfo()
4480 {
4481 return pattern_->ProvideRestoreInfo();
4482 }
4483
RemoveImmediately() const4484 bool FrameNode::RemoveImmediately() const
4485 {
4486 auto context = GetRenderContext();
4487 CHECK_NULL_RETURN(context, true);
4488 // has transition out animation, need to wait for animation end
4489 return !context->HasTransitionOutAnimation();
4490 }
4491
GetNodesById(const std::unordered_set<int32_t> & set)4492 std::vector<RefPtr<FrameNode>> FrameNode::GetNodesById(const std::unordered_set<int32_t>& set)
4493 {
4494 std::vector<int32_t> ids(set.begin(), set.end());
4495 std::vector<RefPtr<FrameNode>> nodes;
4496 for (auto nodeId : ids) {
4497 auto uiNode = ElementRegister::GetInstance()->GetUINodeById(nodeId);
4498 if (!uiNode) {
4499 continue;
4500 }
4501 auto frameNode = DynamicCast<FrameNode>(uiNode);
4502 if (frameNode) {
4503 nodes.emplace_back(frameNode);
4504 }
4505 }
4506 return nodes;
4507 }
4508
GetNodesPtrById(const std::unordered_set<int32_t> & set)4509 std::vector<FrameNode*> FrameNode::GetNodesPtrById(const std::unordered_set<int32_t>& set)
4510 {
4511 std::vector<FrameNode*> nodes;
4512 for (auto nodeId : set) {
4513 NG::FrameNode* frameNode = ElementRegister::GetInstance()->GetFrameNodePtrById(nodeId);
4514 if (!frameNode) {
4515 continue;
4516 }
4517 nodes.emplace_back(frameNode);
4518 }
4519 return nodes;
4520 }
4521
GetPreviewScaleVal()4522 double FrameNode::GetPreviewScaleVal()
4523 {
4524 double scale = 1.0;
4525 auto maxWidth = DragDropManager::GetMaxWidthBaseOnGridSystem(GetContextRefPtr());
4526 auto geometryNode = GetGeometryNode();
4527 CHECK_NULL_RETURN(geometryNode, scale);
4528 auto width = geometryNode->GetFrameRect().Width();
4529 auto previewOption = GetDragPreviewOption();
4530 if (tag_ != V2::WEB_ETS_TAG && width != 0 && width > maxWidth && previewOption.isScaleEnabled) {
4531 scale = maxWidth / width;
4532 }
4533 return scale;
4534 }
4535
IsPreviewNeedScale()4536 bool FrameNode::IsPreviewNeedScale()
4537 {
4538 return GetPreviewScaleVal() < 1.0f;
4539 }
4540
GetNodeExpectedRate()4541 int32_t FrameNode::GetNodeExpectedRate()
4542 {
4543 if (sceneRateMap_.empty()) {
4544 return 0;
4545 }
4546 auto iter = std::max_element(
4547 sceneRateMap_.begin(), sceneRateMap_.end(), [](auto a, auto b) { return a.second < b.second; });
4548 return iter->second;
4549 }
4550
TryPrintDebugLog(const std::string & scene,float speed,SceneStatus status)4551 void FrameNode::TryPrintDebugLog(const std::string& scene, float speed, SceneStatus status)
4552 {
4553 if (SystemProperties::GetDebugEnabled()) {
4554 const std::string sceneStatusStrs[] = { "START", "RUNNING", "END" };
4555 LOGD("%{public}s AddFRCSceneInfo scene:%{public}s speed:%{public}f status:%{public}s", tag_.c_str(),
4556 scene.c_str(), std::abs(speed), sceneStatusStrs[static_cast<int32_t>(status)].c_str());
4557 }
4558 }
4559
AddFRCSceneInfo(const std::string & scene,float speed,SceneStatus status)4560 void FrameNode::AddFRCSceneInfo(const std::string& scene, float speed, SceneStatus status)
4561 {
4562 TryPrintDebugLog(scene, speed, status);
4563
4564 auto renderContext = GetRenderContext();
4565 CHECK_NULL_VOID(renderContext);
4566 auto pipelineContext = GetContext();
4567 CHECK_NULL_VOID(pipelineContext);
4568 auto frameRateManager = pipelineContext->GetFrameRateManager();
4569 CHECK_NULL_VOID(frameRateManager);
4570
4571 frameRateManager->SetDragScene(status == SceneStatus::END ? 0 : 1);
4572 auto expectedRate = renderContext->CalcExpectedFrameRate(scene, std::abs(speed));
4573 auto nodeId = nodeId_;
4574 auto iter = sceneRateMap_.find(scene);
4575 EventReport::FrameRateDurationsStatistics(expectedRate, scene, status);
4576
4577 switch (status) {
4578 case SceneStatus::START: {
4579 if (iter == sceneRateMap_.end()) {
4580 if (sceneRateMap_.empty()) {
4581 frameRateManager->AddNodeRate(nodeId);
4582 }
4583 sceneRateMap_.emplace(scene, expectedRate);
4584 frameRateManager->UpdateNodeRate(nodeId, GetNodeExpectedRate());
4585 }
4586 return;
4587 }
4588 case SceneStatus::RUNNING: {
4589 if (iter != sceneRateMap_.end() && iter->second != expectedRate) {
4590 iter->second = expectedRate;
4591 auto nodeExpectedRate = GetNodeExpectedRate();
4592 frameRateManager->UpdateNodeRate(nodeId, nodeExpectedRate);
4593 }
4594 return;
4595 }
4596 case SceneStatus::END: {
4597 if (iter != sceneRateMap_.end()) {
4598 sceneRateMap_.erase(iter);
4599 if (sceneRateMap_.empty()) {
4600 frameRateManager->RemoveNodeRate(nodeId);
4601 } else {
4602 auto nodeExpectedRate = GetNodeExpectedRate();
4603 frameRateManager->UpdateNodeRate(nodeId, nodeExpectedRate);
4604 }
4605 }
4606 return;
4607 }
4608 default:
4609 return;
4610 }
4611 }
4612
GetPercentSensitive()4613 void FrameNode::GetPercentSensitive()
4614 {
4615 auto res = layoutProperty_->GetPercentSensitive();
4616 if (res.first) {
4617 if (layoutAlgorithm_) {
4618 layoutAlgorithm_->SetPercentWidth(true);
4619 }
4620 }
4621 if (res.second) {
4622 if (layoutAlgorithm_) {
4623 layoutAlgorithm_->SetPercentHeight(true);
4624 }
4625 }
4626 }
4627
UpdatePercentSensitive()4628 void FrameNode::UpdatePercentSensitive()
4629 {
4630 bool percentHeight = layoutAlgorithm_ ? layoutAlgorithm_->GetPercentHeight() : true;
4631 bool percentWidth = layoutAlgorithm_ ? layoutAlgorithm_->GetPercentWidth() : true;
4632 auto res = layoutProperty_->UpdatePercentSensitive(percentWidth, percentHeight);
4633 if (res.first) {
4634 auto parent = GetAncestorNodeOfFrame(true);
4635 if (parent && parent->layoutAlgorithm_) {
4636 parent->layoutAlgorithm_->SetPercentWidth(true);
4637 }
4638 }
4639 if (res.second) {
4640 auto parent = GetAncestorNodeOfFrame(true);
4641 if (parent && parent->layoutAlgorithm_) {
4642 parent->layoutAlgorithm_->SetPercentHeight(true);
4643 }
4644 }
4645 }
4646
PreMeasure(const std::optional<LayoutConstraintF> & parentConstraint)4647 bool FrameNode::PreMeasure(const std::optional<LayoutConstraintF>& parentConstraint)
4648 {
4649 if (GetEscapeDelayForIgnore() || (GetIgnoreLayoutProcess() && GetHasPreMeasured())) {
4650 return false;
4651 }
4652 auto parent = GetAncestorNodeOfFrame(true);
4653 CHECK_NULL_RETURN(parent, false);
4654 if (parent->ChildPreMeasureHelper(this, parentConstraint)) {
4655 parent->CollectDelayMeasureChild(this);
4656 return true;
4657 }
4658 return false;
4659 }
4660
ChildPreMeasureHelper(LayoutWrapper * childWrapper,const std::optional<LayoutConstraintF> & parentConstraint)4661 bool FrameNode::ChildPreMeasureHelper(
4662 LayoutWrapper* childWrapper, const std::optional<LayoutConstraintF>& parentConstraint)
4663 {
4664 auto pattern = GetPattern();
4665 if (!pattern->ChildPreMeasureHelperEnabled()) {
4666 return false;
4667 }
4668 CHECK_NULL_RETURN(childWrapper, false);
4669 auto layoutProperty = childWrapper->GetLayoutProperty();
4670 CHECK_NULL_RETURN(layoutProperty, false);
4671 if (!layoutProperty->IsIgnoreOptsValid()) {
4672 return false;
4673 }
4674 auto childNode = childWrapper->GetHostNode();
4675 if (childNode) {
4676 childNode->SetDelaySelfLayoutForIgnore();
4677 AddDelayLayoutChild(childNode);
4678 }
4679 bool needDelayMeasure = false;
4680 if (pattern->ChildPreMeasureHelperCustomized()) {
4681 needDelayMeasure = pattern->ChildPreMeasureHelper(childWrapper, parentConstraint);
4682 } else {
4683 needDelayMeasure = PredictMeasureResult(childWrapper, parentConstraint);
4684 }
4685 if (needDelayMeasure && childNode) {
4686 childNode->SetHasPreMeasured();
4687 }
4688 return needDelayMeasure;
4689 }
4690
CollectDelayMeasureChild(LayoutWrapper * childWrapper)4691 void FrameNode::CollectDelayMeasureChild(LayoutWrapper* childWrapper)
4692 {
4693 CHECK_NULL_VOID(childWrapper);
4694 auto childNode = childWrapper->GetHostNode();
4695 CHECK_NULL_VOID(childNode);
4696 delayMeasureChildren_.emplace_back(childNode);
4697 }
4698
PostTaskForIgnore()4699 void FrameNode::PostTaskForIgnore()
4700 {
4701 if (delayMeasureChildren_.empty() && delayLayoutChildren_.empty()) {
4702 return;
4703 }
4704 PostBundle(std::move(delayMeasureChildren_));
4705 }
4706
PostBundle(std::vector<RefPtr<FrameNode>> && nodes)4707 void FrameNode::PostBundle(std::vector<RefPtr<FrameNode>>&& nodes)
4708 {
4709 auto pipeline = GetContext();
4710 CHECK_NULL_VOID(pipeline);
4711 IgnoreLayoutSafeAreaBundle bundle;
4712 bundle.second = Claim(this);
4713 bundle.first = std::move(nodes);
4714 pipeline->AddIgnoreLayoutSafeAreaBundle(std::move(bundle));
4715 }
4716
PostponedTaskForIgnore()4717 bool FrameNode::PostponedTaskForIgnore()
4718 {
4719 auto pattern = GetPattern();
4720 if (!pattern->PostponedTaskForIgnoreEnabled()) {
4721 delayLayoutChildren_.clear();
4722 return false;
4723 }
4724 if (pattern->PostponedTaskForIgnoreCustomized()) {
4725 pattern->PostponedTaskForIgnore();
4726 } else {
4727 for (auto&& node : delayLayoutChildren_) {
4728 IgnoreLayoutSafeAreaOpts options = { .type = NG::LAYOUT_SAFE_AREA_TYPE_NONE,
4729 .edges = NG::LAYOUT_SAFE_AREA_EDGE_NONE };
4730 auto property = node->GetLayoutProperty();
4731 if (property) {
4732 options = property->GenIgnoreOpts();
4733 }
4734 ExpandEdges sae = node->GetAccumulatedSafeAreaExpand(false, options);
4735 bool isRtl = false;
4736 auto containerProperty = GetLayoutProperty();
4737 if (containerProperty) {
4738 isRtl = containerProperty->DecideMirror();
4739 }
4740 auto selfIgnoreAdjust = isRtl ? sae.MirrorOffset() : sae.Offset();
4741 auto geometryNode = node->GetGeometryNode();
4742 if (geometryNode) {
4743 geometryNode->SetIgnoreAdjust(selfIgnoreAdjust);
4744 auto offset = geometryNode->GetMarginFrameOffset();
4745 offset -= selfIgnoreAdjust;
4746 geometryNode->SetMarginFrameOffset(offset);
4747 }
4748 node->Layout();
4749 }
4750 }
4751 delayLayoutChildren_.clear();
4752 return true;
4753 }
4754
TraverseForIgnore()4755 void FrameNode::TraverseForIgnore()
4756 {
4757 if (!SubtreeWithIgnoreChild() || (layoutProperty_ && layoutProperty_->IsIgnoreOptsValid())) {
4758 return;
4759 }
4760 std::vector<RefPtr<FrameNode>> effectedNodes;
4761 int recheckCount = 0;
4762 TraverseSubtreeToPostBundle(effectedNodes, recheckCount);
4763 if (SystemProperties::GetMeasureDebugTraceEnabled()) {
4764 ACE_MEASURE_SCOPED_TRACE("TraverseForIgnore[%s][self:%d] subtreeIgnoreCount=%d, recheckCount=%d", tag_.c_str(),
4765 nodeId_, subtreeIgnoreCount_, recheckCount);
4766 }
4767 if (recheckCount != subtreeIgnoreCount_) {
4768 UpdateIgnoreCount(recheckCount - subtreeIgnoreCount_);
4769 }
4770 if (!effectedNodes.empty()) {
4771 PostBundle(std::move(effectedNodes));
4772 }
4773 }
4774
TraverseSubtreeToPostBundle(std::vector<RefPtr<FrameNode>> & subtreeCollection,int & subtreeRecheck)4775 void FrameNode::TraverseSubtreeToPostBundle(std::vector<RefPtr<FrameNode>>& subtreeCollection, int& subtreeRecheck)
4776 {
4777 std::list<RefPtr<FrameNode>> children;
4778 GenerateOneDepthVisibleFrame(children);
4779 for (const auto& child : children) {
4780 if (!child || !child->SubtreeWithIgnoreChild()) {
4781 continue;
4782 }
4783 auto property = child->GetLayoutProperty();
4784 if (property && property->IsIgnoreOptsValid()) {
4785 subtreeCollection.emplace_back(child);
4786 } else {
4787 std::vector<RefPtr<FrameNode>> effectedNodes;
4788 int recheckCount = 0;
4789 child->TraverseSubtreeToPostBundle(effectedNodes, recheckCount);
4790 if (recheckCount != child->subtreeIgnoreCount_) {
4791 child->UpdateIgnoreCount(recheckCount - child->subtreeIgnoreCount_);
4792 }
4793 if (!effectedNodes.empty()) {
4794 child->PostBundle(std::move(effectedNodes));
4795 }
4796 }
4797 subtreeRecheck += child->subtreeIgnoreCount_;
4798 }
4799 }
4800
EnsureDelayedMeasureBeingOnlyOnce()4801 bool FrameNode::EnsureDelayedMeasureBeingOnlyOnce()
4802 {
4803 auto parent = GetAncestorNodeOfFrame(true);
4804 CHECK_NULL_RETURN(parent, false);
4805 auto pattern = parent->GetPattern();
4806 CHECK_NULL_RETURN(pattern, false);
4807 if (pattern->ChildPreMeasureHelperEnabled() && !CheckHasPreMeasured()) {
4808 return true;
4809 }
4810 return false;
4811 }
4812
4813 // This will call child and self measure process.
Measure(const std::optional<LayoutConstraintF> & parentConstraint)4814 void FrameNode::Measure(const std::optional<LayoutConstraintF>& parentConstraint)
4815 {
4816 if (GetIgnoreLayoutProcess() && EnsureDelayedMeasureBeingOnlyOnce()) {
4817 return;
4818 }
4819 ACE_LAYOUT_TRACE_BEGIN("Measure[%s][self:%d][parent:%d][key:%s]", tag_.c_str(), nodeId_,
4820 GetAncestorNodeOfFrame(true) ? GetAncestorNodeOfFrame(true)->GetId() : 0, GetInspectorIdValue("").c_str());
4821 if (SystemProperties::GetMeasureDebugTraceEnabled()) {
4822 ACE_MEASURE_SCOPED_TRACE("MeasureInfo[frameRect:%s][parentConstraint:%s][calcConstraint:%s]",
4823 GetGeometryNode()->GetFrameRect().ToString().c_str(),
4824 parentConstraint.has_value() ? parentConstraint.value().ToString().c_str() : "NA",
4825 layoutProperty_->GetCalcLayoutConstraint() ? layoutProperty_->GetCalcLayoutConstraint()->ToString().c_str()
4826 : "NA");
4827 }
4828 auto pipeline = GetContext();
4829 if (pipeline) {
4830 auto id = pipeline->GetInstanceId();
4831 ArkUIPerfMonitor::GetPerfMonitor(id)->RecordLayoutNode();
4832 }
4833 isLayoutComplete_ = false;
4834 if (!oldGeometryNode_) {
4835 oldGeometryNode_ = geometryNode_->Clone();
4836 }
4837 pattern_->BeforeCreateLayoutWrapper();
4838 GetLayoutAlgorithm(true);
4839
4840 if (layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE) == VisibleType::GONE) {
4841 layoutAlgorithm_->SetSkipMeasure();
4842 layoutAlgorithm_->SetSkipLayout();
4843 geometryNode_->SetFrameSize(SizeF());
4844 geometryNode_->UpdateMargin(MarginPropertyF());
4845 isLayoutDirtyMarked_ = false;
4846 ACE_SCOPED_TRACE("SkipMeasure [%s][self:%d] reason: VisibleType::GONE", tag_.c_str(), nodeId_);
4847 ACE_LAYOUT_TRACE_END()
4848 return;
4849 }
4850 if (!isActive_) {
4851 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
4852 }
4853
4854 if (layoutAlgorithm_->SkipMeasure()) {
4855 isLayoutDirtyMarked_ = false;
4856 ACE_LAYOUT_TRACE_END()
4857 ACE_SCOPED_TRACE("SkipMeasure [%s][self:%d] reason: SkipMeasure", tag_.c_str(), nodeId_);
4858 return;
4859 }
4860
4861 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
4862 if (geometryTransition != nullptr && geometryTransition->IsRunning(WeakClaim(this))) {
4863 geometryTransition->WillLayout(Claim(this));
4864 }
4865 auto preConstraint = layoutProperty_->GetLayoutConstraint();
4866 auto contentConstraint = layoutProperty_->GetContentLayoutConstraint();
4867 layoutProperty_->BuildGridProperty(Claim(this));
4868
4869 if (layoutProperty_->GetLayoutRect()) {
4870 layoutProperty_->UpdateLayoutConstraintWithLayoutRect();
4871 } else if (parentConstraint) {
4872 ApplyConstraint(*parentConstraint);
4873 } else {
4874 CreateRootConstraint();
4875 }
4876
4877 if (PreMeasure(parentConstraint)) {
4878 return;
4879 }
4880
4881 layoutProperty_->UpdateContentConstraint();
4882 geometryNode_->UpdateMargin(layoutProperty_->CreateMargin());
4883 geometryNode_->UpdatePaddingWithBorder(layoutProperty_->CreatePaddingAndBorder());
4884
4885 isConstraintNotChanged_ = layoutProperty_->ConstraintEqual(preConstraint, contentConstraint);
4886
4887 isLayoutDirtyMarked_ = false;
4888
4889 if (isConstraintNotChanged_) {
4890 if (!CheckNeedForceMeasureAndLayout()) {
4891 TraverseForIgnore();
4892 ACE_SCOPED_TRACE(
4893 "SkipMeasure [%s][self:%d] reason:ConstraintNotChanged and no force-flag", tag_.c_str(), nodeId_);
4894 layoutAlgorithm_->SetSkipMeasure();
4895 ACE_LAYOUT_TRACE_END()
4896 return;
4897 }
4898 } else {
4899 contentConstraintChanges_.UpdateFlags(contentConstraint, layoutProperty_->GetContentLayoutConstraint());
4900 constraintChanges_.UpdateFlags(preConstraint, layoutProperty_->GetLayoutConstraint());
4901 }
4902
4903 GetPercentSensitive();
4904
4905 if (extensionHandler_ && !extensionHandler_->HasDrawModifier()) {
4906 auto extensionLayoutConstraint =
4907 ExtensionLayoutConstraint::Create(GetLayoutProperty()->GetLayoutConstraint().value());
4908 extensionHandler_->SetInnerMeasureImpl([this](const ExtensionLayoutConstraint&) {
4909 auto size = layoutAlgorithm_->MeasureContent(layoutProperty_->CreateContentConstraint(), this);
4910 if (size.has_value()) {
4911 geometryNode_->SetContentSize(size.value());
4912 }
4913 layoutAlgorithm_->Measure(this);
4914 });
4915 extensionHandler_->Measure(extensionLayoutConstraint);
4916 } else {
4917 auto size = layoutAlgorithm_->MeasureContent(layoutProperty_->CreateContentConstraint(), this);
4918 if (size.has_value()) {
4919 geometryNode_->SetContentSize(size.value());
4920 }
4921 layoutAlgorithm_->Measure(this);
4922 }
4923
4924 if (overlayNode_) {
4925 overlayNode_->Measure(layoutProperty_->CreateChildConstraint());
4926 }
4927 UpdatePercentSensitive();
4928 // check aspect radio.
4929 if (pattern_ && pattern_->IsNeedAdjustByAspectRatio() && !layoutProperty_->GetLayoutRect()) {
4930 const auto& magicItemProperty = layoutProperty_->GetMagicItemProperty();
4931 auto aspectRatio = magicItemProperty.GetAspectRatioValue();
4932 // Adjust by aspect ratio, firstly pick height based on width. It means that when width, height and
4933 // aspectRatio are all set, the height is not used.
4934 auto width = geometryNode_->GetFrameSize().Width();
4935 auto height = width / aspectRatio;
4936 geometryNode_->SetFrameSize(SizeF({ width, height }));
4937 }
4938
4939 if (pipeline && pipeline->GetPixelRoundMode() == PixelRoundMode::PIXEL_ROUND_AFTER_MEASURE) {
4940 auto size = geometryNode_->GetFrameSize();
4941 geometryNode_->SetPreFrameSize(size);
4942 geometryNode_->SetFrameSize(SizeF({ round(size.Width()), round(size.Height()) }));
4943 }
4944
4945 if (measureCallback_) {
4946 measureCallback_(kitNode_);
4947 }
4948
4949 PostTaskForIgnore();
4950
4951 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_LAYOUT);
4952 if (SystemProperties::GetMeasureDebugTraceEnabled()) {
4953 ACE_MEASURE_SCOPED_TRACE("MeasureFinish[frameRect:%s][contentSize:%s]",
4954 GetGeometryNode()->GetFrameRect().ToString().c_str(),
4955 GetGeometryNode()->GetContentSize().ToString().c_str());
4956 }
4957 ACE_LAYOUT_TRACE_END()
4958 }
4959
4960 // Called to perform layout children.
Layout()4961 void FrameNode::Layout()
4962 {
4963 if (GetDelaySelfLayoutForIgnore()) {
4964 return;
4965 }
4966
4967 ACE_LAYOUT_TRACE_BEGIN("Layout[%s][self:%d][parent:%d][key:%s]", tag_.c_str(), nodeId_,
4968 GetAncestorNodeOfFrame(true) ? GetAncestorNodeOfFrame(true)->GetId() : 0, GetInspectorIdValue("").c_str());
4969 if (SystemProperties::GetMeasureDebugTraceEnabled()) {
4970 ACE_MEASURE_SCOPED_TRACE("LayoutInfo[frameRect:%s]", GetGeometryNode()->GetFrameRect().ToString().c_str());
4971 }
4972 if (layoutProperty_->GetLayoutRect()) {
4973 GetGeometryNode()->SetFrameOffset(layoutProperty_->GetLayoutRect().value().GetOffset());
4974 }
4975 int64_t time = GetSysTimestamp();
4976 OffsetNodeToSafeArea();
4977 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
4978 if (geometryTransition != nullptr) {
4979 if (geometryTransition->IsNodeInAndActive(Claim(this))) {
4980 if (IsRootMeasureNode()) {
4981 UINode::SetGeometryTransitionInRecursive(true);
4982 } else {
4983 SetSkipSyncGeometryNode();
4984 }
4985 }
4986 }
4987 if (CheckNeedLayout(layoutProperty_->GetPropertyChangeFlag()) || GetIgnoreLayoutProcess()) {
4988 if (!layoutProperty_->GetLayoutConstraint()) {
4989 const auto& parentLayoutConstraint = geometryNode_->GetParentLayoutConstraint();
4990 if (layoutProperty_->GetLayoutRect()) {
4991 layoutProperty_->UpdateLayoutConstraintWithLayoutRect();
4992 } else if (parentLayoutConstraint) {
4993 layoutProperty_->UpdateLayoutConstraint(parentLayoutConstraint.value());
4994 } else {
4995 LayoutConstraintF layoutConstraint;
4996 layoutConstraint.percentReference.SetWidth(PipelineContext::GetCurrentRootWidth());
4997 layoutConstraint.percentReference.SetHeight(PipelineContext::GetCurrentRootHeight());
4998 layoutProperty_->UpdateLayoutConstraint(layoutConstraint);
4999 }
5000 layoutProperty_->UpdateContentConstraint();
5001 }
5002
5003 if (extensionHandler_ && !extensionHandler_->HasDrawModifier()) {
5004 extensionHandler_->SetInnerLayoutImpl(
5005 [this](int32_t, int32_t, int32_t, int32_t) { GetLayoutAlgorithm()->Layout(this); });
5006 const auto& rect = geometryNode_->GetFrameRect();
5007 extensionHandler_->Layout(rect.Width(), rect.Height(), rect.GetX(), rect.GetY());
5008 } else {
5009 GetLayoutAlgorithm()->Layout(this);
5010 }
5011
5012 if (overlayNode_) {
5013 LayoutOverlay();
5014 }
5015 time = GetSysTimestamp() - time;
5016 AddNodeFlexLayouts();
5017 AddNodeLayoutTime(time);
5018 } else {
5019 ACE_SCOPED_TRACE("SkipLayout [%s][self:%d]", tag_.c_str(), nodeId_);
5020 GetLayoutAlgorithm()->SetSkipLayout();
5021 }
5022 if (SystemProperties::GetMeasureDebugTraceEnabled()) {
5023 ACE_MEASURE_SCOPED_TRACE(
5024 "LayoutFinish[frameRect:%s]", GetGeometryNode()->GetFrameRect().ToString().c_str());
5025 }
5026
5027 auto pipeline = GetContext();
5028 CHECK_NULL_VOID_LAYOUT_TRACE_END(pipeline);
5029 auto stageManager = pipeline->GetStageManager();
5030 CHECK_NULL_VOID(stageManager);
5031 bool isFocusOnPage = stageManager->CheckPageFocus();
5032 bool needSyncRsNode = false;
5033 DirtySwapConfig config;
5034 bool willSyncGeoProperties = OnLayoutFinish(needSyncRsNode, config);
5035 needSyncRsNode |= AvoidKeyboard(isFocusOnPage);
5036 if (GetIsGeometryTransitionIn()) {
5037 renderContext_->SetFrameWithoutAnimation(renderContext_->GetPaintRectWithoutTransform());
5038 SetIsGeometryTransitionIn(false);
5039 }
5040 // skip wrapping task if node will not sync
5041 CHECK_NULL_VOID_LAYOUT_TRACE_END(willSyncGeoProperties);
5042 auto task = [weak = WeakClaim(this), needSync = needSyncRsNode, dirtyConfig = config]() {
5043 auto frameNode = weak.Upgrade();
5044 CHECK_NULL_VOID(frameNode);
5045 frameNode->SyncGeometryNode(needSync, dirtyConfig);
5046 };
5047 pipeline->AddSyncGeometryNodeTask(task);
5048 if (SelfOrParentExpansive()) {
5049 auto pipeline = GetContext();
5050 CHECK_NULL_VOID_LAYOUT_TRACE_END(pipeline);
5051 auto safeAreaManager = pipeline->GetSafeAreaManager();
5052 CHECK_NULL_VOID_LAYOUT_TRACE_END(safeAreaManager);
5053 safeAreaManager->AddNeedExpandNode(GetHostNode());
5054 }
5055 // if a node has geo transition but not the root node, add task only but not flush
5056 // or add to expand list, self node will be added to expand list in next layout
5057 if (geometryTransition != nullptr && !IsRootMeasureNode()) {
5058 ACE_LAYOUT_TRACE_END()
5059 return;
5060 }
5061 if (geometryTransition != nullptr) {
5062 pipeline->FlushSyncGeometryNodeTasks();
5063 }
5064 ACE_LAYOUT_TRACE_END()
5065 }
5066
SelfExpansive()5067 bool FrameNode::SelfExpansive()
5068 {
5069 auto&& opts = GetLayoutProperty()->GetSafeAreaExpandOpts();
5070 return opts && (opts->Expansive() || opts->switchToNone);
5071 }
5072
SelfExpansiveToKeyboard()5073 bool FrameNode::SelfExpansiveToKeyboard()
5074 {
5075 auto && opts = GetLayoutProperty()->GetSafeAreaExpandOpts();
5076 return opts && opts->ExpansiveToKeyboard();
5077 }
5078
ParentExpansive()5079 bool FrameNode::ParentExpansive()
5080 {
5081 auto parent = GetAncestorNodeOfFrame(false);
5082 CHECK_NULL_RETURN(parent, false);
5083 auto parentLayoutProperty = parent->GetLayoutProperty();
5084 CHECK_NULL_RETURN(parentLayoutProperty, false);
5085 auto&& parentOpts = parentLayoutProperty->GetSafeAreaExpandOpts();
5086 return parentOpts && parentOpts->Expansive();
5087 }
5088
ProcessSafeAreaPadding()5089 void FrameNode::ProcessSafeAreaPadding()
5090 {
5091 pattern_->ProcessSafeAreaPadding();
5092 }
5093
UpdateFocusState()5094 void FrameNode::UpdateFocusState()
5095 {
5096 auto focusHub = GetFocusHub();
5097 if (focusHub && focusHub->IsCurrentFocus()) {
5098 focusHub->ClearFocusState(false);
5099 focusHub->PaintFocusState(false);
5100 }
5101 }
5102
SelfOrParentExpansive()5103 bool FrameNode::SelfOrParentExpansive()
5104 {
5105 return SelfExpansive() || ParentExpansive();
5106 }
5107
ProcessAccessibilityVirtualNode()5108 void FrameNode::ProcessAccessibilityVirtualNode()
5109 {
5110 if (!hasAccessibilityVirtualNode_) {
5111 return;
5112 }
5113 auto accessibilityProperty = GetAccessibilityProperty<AccessibilityProperty>();
5114 auto virtualNode = accessibilityProperty->GetAccessibilityVirtualNode();
5115 auto virtualFrameNode = AceType::DynamicCast<NG::FrameNode>(virtualNode);
5116 if (virtualFrameNode) {
5117 auto constraint = GetLayoutConstraint();
5118 virtualFrameNode->ApplyConstraint(constraint);
5119 ProcessOffscreenNode(virtualFrameNode);
5120 }
5121 }
5122
UpdateAccessibilityNodeRect()5123 void FrameNode::UpdateAccessibilityNodeRect()
5124 {
5125 if (!AceApplicationInfo::GetInstance().IsAccessibilityScreenReadEnabled()) {
5126 return;
5127 }
5128 auto context = GetContextRefPtr();
5129 CHECK_NULL_VOID(context);
5130 auto accessibilityManager = context->GetAccessibilityManager();
5131 CHECK_NULL_VOID(accessibilityManager);
5132 accessibilityManager->UpdateAccessibilityNodeRect(Claim(this));
5133 }
5134
OnLayoutFinish(bool & needSyncRsNode,DirtySwapConfig & config)5135 bool FrameNode::OnLayoutFinish(bool& needSyncRsNode, DirtySwapConfig& config)
5136 {
5137 auto context = GetContext();
5138 if (isLayoutNode_ && context) {
5139 context->AddLayoutNode(Claim(this));
5140 }
5141 isLayoutComplete_ = true;
5142 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
5143 bool hasTransition = geometryTransition != nullptr && geometryTransition->IsRunning(WeakClaim(this));
5144 if ((!isActive_ && !hasTransition) ||
5145 (needSkipSyncGeometryNode_ && (!geometryTransition || !geometryTransition->IsNodeInAndActive(Claim(this))))) {
5146 ACE_SCOPED_TRACE("OnLayoutFinish[%s][self:%d] isActive:%d, hasTransition:%d, needSkipSyncGeometryNode:%d",
5147 GetTag().c_str(), GetId(), isActive_, hasTransition, needSkipSyncGeometryNode_);
5148 if (context && layoutAlgorithm_ && layoutAlgorithm_->MeasureInNextFrame()) {
5149 isLayoutDirtyMarked_ = true;
5150 context->AddDirtyLayoutNode(Claim(this));
5151 }
5152 layoutAlgorithm_.Reset();
5153 return false;
5154 }
5155 // update layout size.
5156 bool frameSizeChange = true;
5157 bool frameOffsetChange = true;
5158 bool contentSizeChange = true;
5159 bool contentOffsetChange = true;
5160 if (oldGeometryNode_) {
5161 frameSizeChange = geometryNode_->GetFrameSize() != oldGeometryNode_->GetFrameSize();
5162 frameOffsetChange = geometryNode_->GetFrameOffset() != oldGeometryNode_->GetFrameOffset();
5163 contentSizeChange = geometryNode_->GetContentSize() != oldGeometryNode_->GetContentSize();
5164 contentOffsetChange = geometryNode_->GetContentOffset() != oldGeometryNode_->GetContentOffset();
5165 oldGeometryNode_.Reset();
5166 }
5167
5168 // clean layout flag.
5169 layoutProperty_->CleanDirty();
5170 needSyncRsNode = frameSizeChange || frameOffsetChange ||
5171 (pattern_->GetContextParam().has_value() && contentSizeChange) || HasPositionProp() ||
5172 SelfOrParentExpansive();
5173 if (hasTransition) {
5174 geometryTransition->DidLayout(Claim(this));
5175 if (geometryTransition->IsNodeOutAndActive(WeakClaim(this))) {
5176 isLayoutDirtyMarked_ = true;
5177 }
5178 needSyncRsNode = false;
5179 } else if (frameSizeChange && renderContext_->IsSynced()) {
5180 auto borderRadius = renderContext_->GetBorderRadius();
5181 if (borderRadius.has_value()) {
5182 renderContext_->SetBorderRadius(borderRadius.value());
5183 }
5184 auto outerBorderRadius = renderContext_->GetOuterBorderRadius();
5185 if (outerBorderRadius.has_value()) {
5186 renderContext_->SetOuterBorderRadius(outerBorderRadius.value());
5187 }
5188 }
5189 if (tag_ != V2::PAGE_ETS_TAG) {
5190 renderContext_->SavePaintRect(true, layoutProperty_->GetPixelRound());
5191 if (needSyncRsNode) {
5192 renderContext_->SyncPartialRsProperties();
5193 }
5194 }
5195 config = { .frameSizeChange = frameSizeChange,
5196 .frameOffsetChange = frameOffsetChange,
5197 .contentSizeChange = contentSizeChange,
5198 .contentOffsetChange = contentOffsetChange };
5199 // check if need to paint content.
5200 auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(layoutAlgorithm_);
5201 CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
5202 config.skipMeasure = layoutAlgorithmWrapper->SkipMeasure();
5203 config.skipLayout = layoutAlgorithmWrapper->SkipLayout();
5204 if (!config.skipMeasure && !config.skipLayout) {
5205 CHECK_NULL_RETURN(context, false);
5206 if (GetInspectorId()) {
5207 context->OnLayoutCompleted(GetInspectorId()->c_str());
5208 }
5209 if (eventHub_) {
5210 eventHub_->FireLayoutNDKCallback(context);
5211 }
5212 }
5213 auto needRerender = pattern_->OnDirtyLayoutWrapperSwap(Claim(this), config);
5214 needRerender =
5215 needRerender || pattern_->OnDirtyLayoutWrapperSwap(Claim(this), config.skipMeasure, config.skipLayout);
5216 if (GreatOrEqualAPITargetVersion(PlatformVersion::VERSION_TWENTY)) {
5217 auto skippedMeasure = config.skipMeasure || SkipMeasureContent();
5218 needRerender = needRerender || (extensionHandler_ &&
5219 (extensionHandler_->NeedRender() || (extensionHandler_->HasDrawModifier() && !skippedMeasure)));
5220 } else {
5221 needRerender = needRerender || (extensionHandler_ && extensionHandler_->NeedRender());
5222 }
5223 if (needRerender || CheckNeedRender(paintProperty_->GetPropertyChangeFlag())) {
5224 MarkDirtyNode(true, true, PROPERTY_UPDATE_RENDER);
5225 }
5226 layoutAlgorithm_.Reset();
5227
5228 UpdateAccessibilityNodeRect();
5229 ProcessAccessibilityVirtualNode();
5230 CHECK_NULL_RETURN(context, false);
5231 context->SendUpdateVirtualNodeFocusEvent();
5232 return true;
5233 }
5234
SyncGeometryNode(bool needSyncRsNode,const DirtySwapConfig & config)5235 void FrameNode::SyncGeometryNode(bool needSyncRsNode, const DirtySwapConfig& config)
5236 {
5237 if (SystemProperties::GetSyncDebugTraceEnabled()) {
5238 ACE_LAYOUT_TRACE_BEGIN("SyncGeometryNode[%s][self:%d][parent:%d][key:%s][paintRect:%s][needSyncRsNode:%d]",
5239 tag_.c_str(), nodeId_, GetParent() ? GetParent()->GetId() : 0, GetInspectorIdValue("").c_str(),
5240 renderContext_->GetPaintRectWithoutTransform().ToString().c_str(), needSyncRsNode);
5241 ACE_LAYOUT_TRACE_END()
5242 }
5243
5244 // update border.
5245 if (layoutProperty_->GetBorderWidthProperty()) {
5246 if (!renderContext_->HasBorderColor()) {
5247 BorderColorProperty borderColorProperty;
5248 borderColorProperty.SetColor(Color::BLACK);
5249 renderContext_->UpdateBorderColor(borderColorProperty);
5250 }
5251 if (!renderContext_->HasBorderStyle()) {
5252 BorderStyleProperty borderStyleProperty;
5253 borderStyleProperty.SetBorderStyle(BorderStyle::SOLID);
5254 renderContext_->UpdateBorderStyle(borderStyleProperty);
5255 }
5256 if (!renderContext_->HasDashGap()) {
5257 BorderWidthProperty dashGapProperty;
5258 dashGapProperty.SetBorderWidth(Dimension(-1));
5259 renderContext_->UpdateDashGap(dashGapProperty);
5260 }
5261 if (!renderContext_->HasDashWidth()) {
5262 BorderWidthProperty dashWidthProperty;
5263 dashWidthProperty.SetBorderWidth(Dimension(-1));
5264 renderContext_->UpdateDashWidth(dashWidthProperty);
5265 }
5266 if (layoutProperty_->GetLayoutConstraint().has_value()) {
5267 renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
5268 ScaleProperty::CreateScaleProperty(),
5269 layoutProperty_->GetLayoutConstraint()->percentReference.Width()));
5270 } else {
5271 renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
5272 ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth()));
5273 }
5274 }
5275
5276 pattern_->OnSyncGeometryNode(config);
5277 if (needSyncRsNode) {
5278 pattern_->BeforeSyncGeometryProperties(config);
5279 renderContext_->SyncGeometryProperties(RawPtr(geometryNode_), true, layoutProperty_->GetPixelRound());
5280 if (SystemProperties::GetSyncDebugTraceEnabled()) {
5281 ACE_LAYOUT_TRACE_BEGIN("TriggerOnSizeChangeNode:[%s][id:%d]", tag_.c_str(), nodeId_);
5282 ACE_LAYOUT_TRACE_END()
5283 }
5284 TriggerOnSizeChangeCallback();
5285 }
5286
5287 UpdateBackground();
5288
5289 // update focus state
5290 UpdateFocusState();
5291
5292 // rebuild child render node.
5293 if (!isLayoutNode_) {
5294 RebuildRenderContextTree();
5295 } else if (GetParent()) {
5296 GetParent()->RebuildRenderContextTree();
5297 }
5298
5299 /* Adjust components' position which have been set grid properties */
5300 AdjustGridOffset();
5301 }
5302
GetOrCreateChildByIndex(uint32_t index,bool addToRenderTree,bool isCache)5303 RefPtr<LayoutWrapper> FrameNode::GetOrCreateChildByIndex(uint32_t index, bool addToRenderTree, bool isCache)
5304 {
5305 if (arkoalaLazyAdapter_) {
5306 return ArkoalaGetOrCreateChild(index, addToRenderTree);
5307 }
5308 auto child = frameProxy_->GetFrameNodeByIndex(index, true, isCache, addToRenderTree);
5309 if (child) {
5310 child->SetSkipSyncGeometryNode(SkipSyncGeometryNode());
5311 if (addToRenderTree) {
5312 child->SetActive(true);
5313 }
5314 }
5315 return child;
5316 }
5317
GetChildByIndex(uint32_t index,bool isCache)5318 RefPtr<LayoutWrapper> FrameNode::GetChildByIndex(uint32_t index, bool isCache)
5319 {
5320 if (arkoalaLazyAdapter_) {
5321 return arkoalaLazyAdapter_->GetChild(index);
5322 }
5323 return frameProxy_->GetFrameNodeByIndex(index, false, isCache, false);
5324 }
5325
GetFrameNodeChildByIndex(uint32_t index,bool isCache,bool isExpand)5326 FrameNode* FrameNode::GetFrameNodeChildByIndex(uint32_t index, bool isCache, bool isExpand)
5327 {
5328 auto frameNode = isExpand ? DynamicCast<FrameNode>(frameProxy_->GetFrameNodeByIndex(index, true, isCache, false))
5329 : DynamicCast<FrameNode>(UINode::GetFrameChildByIndexWithoutExpanded(index));
5330 return RawPtr(frameNode);
5331 }
5332
GetFrameNodeChildByIndexWithoutBuild(uint32_t index)5333 FrameNode* FrameNode::GetFrameNodeChildByIndexWithoutBuild(uint32_t index)
5334 {
5335 auto frameNode = DynamicCast<FrameNode>(UINode::GetFrameChildByIndex(index, false, false, false));
5336 return RawPtr(frameNode);
5337 }
5338
GetChildTrueIndex(const RefPtr<LayoutWrapper> & child) const5339 int32_t FrameNode::GetChildTrueIndex(const RefPtr<LayoutWrapper>& child) const
5340 {
5341 return frameProxy_->GetChildIndex(child);
5342 }
5343
GetChildTrueTotalCount() const5344 uint32_t FrameNode::GetChildTrueTotalCount() const
5345 {
5346 return frameProxy_->GetTotalCount();
5347 }
5348
GetAllChildrenWithBuild(bool addToRenderTree)5349 ChildrenListWithGuard FrameNode::GetAllChildrenWithBuild(bool addToRenderTree)
5350 {
5351 const auto& children = frameProxy_->GetAllFrameChildren();
5352 {
5353 auto guard = frameProxy_->GetGuard();
5354 for (const auto& child : children) {
5355 if (addToRenderTree) {
5356 child->SetActive(true);
5357 }
5358 child->SetSkipSyncGeometryNode(SkipSyncGeometryNode());
5359 }
5360 }
5361
5362 return children;
5363 }
5364
RemoveAllChildInRenderTree()5365 void FrameNode::RemoveAllChildInRenderTree()
5366 {
5367 frameProxy_->RemoveAllChildInRenderTree();
5368 }
5369
SetActiveChildRange(int32_t start,int32_t end,int32_t cacheStart,int32_t cacheEnd,bool showCached)5370 void FrameNode::SetActiveChildRange(int32_t start, int32_t end, int32_t cacheStart, int32_t cacheEnd, bool showCached)
5371 {
5372 if (arkoalaLazyAdapter_) {
5373 return ArkoalaUpdateActiveRange(start, end, cacheStart, cacheEnd, showCached);
5374 }
5375 frameProxy_->SetActiveChildRange(start, end, cacheStart, cacheEnd, showCached);
5376 }
5377
5378 /* ============================== Arkoala LazyForEach adapter section START ==============================*/
ArkoalaSynchronize(LazyComposeAdapter::CreateItemCb creator,LazyComposeAdapter::UpdateRangeCb updater,int32_t totalCount)5379 void FrameNode::ArkoalaSynchronize(
5380 LazyComposeAdapter::CreateItemCb creator, LazyComposeAdapter::UpdateRangeCb updater, int32_t totalCount)
5381 {
5382 if (!arkoalaLazyAdapter_) {
5383 arkoalaLazyAdapter_ = std::make_unique<LazyComposeAdapter>();
5384 }
5385 arkoalaLazyAdapter_->SetCallbacks(std::move(creator), std::move(updater));
5386 arkoalaLazyAdapter_->SetTotalCount(totalCount);
5387 }
5388
ArkoalaRemoveItemsOnChange(int32_t changeIndex)5389 void FrameNode::ArkoalaRemoveItemsOnChange(int32_t changeIndex)
5390 {
5391 CHECK_NULL_VOID(arkoalaLazyAdapter_);
5392 std::vector<RefPtr<UINode>> toRemove;
5393 for (const auto& child : GetChildren()) {
5394 const int32_t index = static_cast<int32_t>(arkoalaLazyAdapter_->GetIndexOfChild(DynamicCast<FrameNode>(child)));
5395 if (index >= changeIndex) {
5396 toRemove.push_back(child);
5397 }
5398 }
5399 for (auto&& node : toRemove) {
5400 RemoveChild(node);
5401 }
5402 arkoalaLazyAdapter_->OnDataChange(changeIndex);
5403 }
5404
ArkoalaUpdateActiveRange(int32_t start,int32_t end,int32_t cacheStart,int32_t cacheEnd,bool showCached)5405 void FrameNode::ArkoalaUpdateActiveRange(int32_t start, int32_t end, int32_t cacheStart, int32_t cacheEnd, bool showCached)
5406 {
5407 CHECK_NULL_VOID(arkoalaLazyAdapter_);
5408 const int32_t liveStart = start - cacheStart;
5409 const int32_t liveEnd = end + cacheEnd;
5410 const int32_t visibleStart = showCached ? liveStart : start;
5411 const int32_t visibleEnd = showCached ? liveEnd : end;
5412 std::vector<RefPtr<UINode>> toRemove;
5413 for (const auto& child : GetChildren()) {
5414 const int32_t index = static_cast<int32_t>(arkoalaLazyAdapter_->GetIndexOfChild(DynamicCast<FrameNode>(child)));
5415 if (index < liveStart || index > liveEnd) {
5416 toRemove.push_back(child);
5417 continue;
5418 }
5419 child->SetActive(index >= visibleStart && index <= visibleEnd);
5420 }
5421 for (auto&& node : toRemove) {
5422 RemoveChild(node);
5423 }
5424 arkoalaLazyAdapter_->SetActiveRange(liveStart, liveEnd);
5425 }
5426
ArkoalaGetOrCreateChild(uint32_t index,bool active)5427 RefPtr<LayoutWrapper> FrameNode::ArkoalaGetOrCreateChild(uint32_t index, bool active)
5428 {
5429 CHECK_NULL_RETURN(arkoalaLazyAdapter_, nullptr);
5430 if (auto node = arkoalaLazyAdapter_->GetChild(index)) {
5431 return node;
5432 }
5433 auto node = arkoalaLazyAdapter_->GetOrCreateChild(index);
5434 CHECK_NULL_RETURN(node, nullptr);
5435 AddChild(node);
5436 node->SetActive(active);
5437 return node;
5438 }
5439 /* ============================== Arkoala LazyForEach adapter section END ================================*/
5440
SetActiveChildRange(const std::optional<ActiveChildSets> & activeChildSets,const std::optional<ActiveChildRange> & activeChildRange)5441 void FrameNode::SetActiveChildRange(
5442 const std::optional<ActiveChildSets>& activeChildSets, const std::optional<ActiveChildRange>& activeChildRange)
5443 {
5444 frameProxy_->SetActiveChildRange(activeChildSets, activeChildRange);
5445 }
5446
RecycleItemsByIndex(int32_t start,int32_t end)5447 void FrameNode::RecycleItemsByIndex(int32_t start, int32_t end)
5448 {
5449 frameProxy_->RecycleItemsByIndex(start, end);
5450 }
5451
RemoveChildInRenderTree(uint32_t index)5452 void FrameNode::RemoveChildInRenderTree(uint32_t index)
5453 {
5454 frameProxy_->RemoveChildInRenderTree(index);
5455 }
5456
SkipMeasureContent() const5457 bool FrameNode::SkipMeasureContent() const
5458 {
5459 return layoutAlgorithm_ && layoutAlgorithm_->SkipMeasure();
5460 }
5461
CheckNeedForceMeasureAndLayout()5462 bool FrameNode::CheckNeedForceMeasureAndLayout()
5463 {
5464 PropertyChangeFlag flag = layoutProperty_->GetPropertyChangeFlag();
5465 return CheckNeedMeasure(flag) || CheckNeedLayout(flag);
5466 }
5467
ReachResponseDeadline() const5468 bool FrameNode::ReachResponseDeadline() const
5469 {
5470 CHECK_NULL_RETURN(context_, false);
5471 return context_->ReachResponseDeadline();
5472 }
5473
GetOffsetInScreen()5474 OffsetF FrameNode::GetOffsetInScreen()
5475 {
5476 auto frameOffset = GetPaintRectOffset(false, true);
5477 auto pipelineContext = PipelineContext::GetCurrentContext();
5478 CHECK_NULL_RETURN(pipelineContext, OffsetF(0.0f, 0.0f));
5479 auto window = pipelineContext->GetWindow();
5480 CHECK_NULL_RETURN(window, OffsetF(0.0f, 0.0f));
5481 auto windowOffset = window->GetCurrentWindowRect().GetOffset();
5482 frameOffset += OffsetT<float> { windowOffset.GetX(), windowOffset.GetY() };
5483 return frameOffset;
5484 }
5485
GetOffsetInSubwindow(const OffsetF & subwindowOffset)5486 OffsetF FrameNode::GetOffsetInSubwindow(const OffsetF& subwindowOffset)
5487 {
5488 auto frameOffset = GetOffsetInScreen();
5489 frameOffset -= subwindowOffset;
5490 return frameOffset;
5491 }
5492
GetDragPixelMap()5493 RefPtr<PixelMap> FrameNode::GetDragPixelMap()
5494 {
5495 auto gestureHub = GetOrCreateGestureEventHub();
5496 CHECK_NULL_RETURN(gestureHub, nullptr);
5497 RefPtr<PixelMap> pixelMap = gestureHub->GetPixelMap();
5498 // if gesture already have pixel map return directly
5499 if (pixelMap) {
5500 return pixelMap;
5501 }
5502 CHECK_NULL_RETURN(renderContext_, nullptr);
5503 pixelMap = renderContext_->GetThumbnailPixelMap();
5504 gestureHub->SetPixelMap(pixelMap);
5505 return pixelMap;
5506 }
5507
GetBaselineDistance() const5508 float FrameNode::GetBaselineDistance() const
5509 {
5510 const auto& children = frameProxy_->GetAllFrameChildren();
5511 if (children.empty()) {
5512 return geometryNode_->GetBaselineDistance();
5513 }
5514 float distance = 0.0;
5515 {
5516 auto guard = frameProxy_->GetGuard();
5517 for (const auto& child : children) {
5518 float childBaseline = child->GetBaselineDistance();
5519 distance = NearZero(distance) ? childBaseline : std::min(distance, childBaseline);
5520 }
5521 }
5522 return distance;
5523 }
5524
MarkNeedSyncRenderTree(bool needRebuild)5525 void FrameNode::MarkNeedSyncRenderTree(bool needRebuild)
5526 {
5527 if (isLayoutNode_ && GetParent()) {
5528 GetParent()->MarkNeedSyncRenderTree(needRebuild);
5529 }
5530 if (needRebuild) {
5531 frameProxy_->ResetChildren(true);
5532 }
5533 needSyncRenderTree_ = true;
5534 }
5535
GetFrameChildByIndex(uint32_t index,bool needBuild,bool isCache,bool addToRenderTree)5536 RefPtr<UINode> FrameNode::GetFrameChildByIndex(uint32_t index, bool needBuild, bool isCache, bool addToRenderTree)
5537 {
5538 if (index != 0) {
5539 return nullptr;
5540 }
5541 return Claim(this);
5542 }
5543
GetFrameChildByIndexWithoutExpanded(uint32_t index)5544 RefPtr<UINode> FrameNode::GetFrameChildByIndexWithoutExpanded(uint32_t index)
5545 {
5546 return GetFrameChildByIndex(index, false);
5547 }
5548
GetLayoutAlgorithm(bool needReset)5549 const RefPtr<LayoutAlgorithmWrapper>& FrameNode::GetLayoutAlgorithm(bool needReset)
5550 {
5551 if ((!layoutAlgorithm_ || (needReset && layoutAlgorithm_->IsExpire())) && pattern_) {
5552 if (kitNode_ && kitNode_->GetPattern()) {
5553 layoutAlgorithm_ =
5554 LayoutAlgorithmWrapper::CreateLayoutAlgorithmWrapper(kitNode_->GetPattern()->CreateLayoutAlgorithm());
5555 } else {
5556 layoutAlgorithm_ = MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm());
5557 }
5558 }
5559 if (needReset) {
5560 layoutAlgorithm_->SetNeedMeasure();
5561 }
5562 return layoutAlgorithm_;
5563 }
5564
SetCacheCount(int32_t cacheCount,const std::optional<LayoutConstraintF> & itemConstraint)5565 void FrameNode::SetCacheCount(int32_t cacheCount, const std::optional<LayoutConstraintF>& itemConstraint)
5566 {
5567 frameProxy_->SetCacheCount(cacheCount, itemConstraint);
5568 }
5569
LayoutOverlay()5570 void FrameNode::LayoutOverlay()
5571 {
5572 auto size = geometryNode_->GetFrameSize();
5573 auto align = Alignment::TOP_LEFT;
5574 Dimension offsetX, offsetY;
5575 auto childLayoutProperty = overlayNode_->GetLayoutProperty();
5576 childLayoutProperty->GetOverlayOffset(offsetX, offsetY);
5577 auto offset = OffsetF(offsetX.ConvertToPx(), offsetY.ConvertToPx());
5578 if (childLayoutProperty->GetPositionProperty()) {
5579 align = childLayoutProperty->GetPositionProperty()->GetAlignment().value_or(align);
5580 }
5581
5582 auto childSize = overlayNode_->GetGeometryNode()->GetMarginFrameSize();
5583 auto translate = Alignment::GetAlignPosition(size, childSize, align) + offset;
5584 overlayNode_->GetGeometryNode()->SetMarginFrameOffset(translate);
5585 overlayNode_->Layout();
5586 }
5587
DoRemoveChildInRenderTree(uint32_t index,bool isAll)5588 void FrameNode::DoRemoveChildInRenderTree(uint32_t index, bool isAll)
5589 {
5590 isActive_ = false;
5591 SetActive(false);
5592 }
5593
DoSetActiveChildRange(int32_t start,int32_t end,int32_t cacheStart,int32_t cacheEnd,bool showCache)5594 void FrameNode::DoSetActiveChildRange(int32_t start, int32_t end, int32_t cacheStart, int32_t cacheEnd, bool showCache)
5595 {
5596 if (showCache) {
5597 start -= cacheStart;
5598 end += cacheEnd;
5599 }
5600 if (start <= end) {
5601 if (start > 0 || end < 0) {
5602 SetActive(false);
5603 SetJSViewActive(false);
5604 } else {
5605 SetActive(true);
5606 SetJSViewActive(true);
5607 }
5608 } else {
5609 if (end < 0 && start > 0) {
5610 SetActive(false);
5611 SetJSViewActive(false);
5612 } else {
5613 SetActive(true);
5614 SetJSViewActive(true);
5615 }
5616 }
5617 }
5618
OnInspectorIdUpdate(const std::string & id)5619 void FrameNode::OnInspectorIdUpdate(const std::string& id)
5620 {
5621 renderContext_->UpdateNodeName(id);
5622 ElementRegister::GetInstance()->AddFrameNodeByInspectorId(id, AceType::WeakClaim(this));
5623 auto parent = GetAncestorNodeOfFrame(true);
5624 if (parent && parent->GetTag() == V2::RELATIVE_CONTAINER_ETS_TAG) {
5625 parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
5626 }
5627 if (Recorder::EventRecorder::Get().IsExposureRecordEnable()) {
5628 if (exposureProcessor_) {
5629 return;
5630 }
5631 auto* context = GetContext();
5632 CHECK_NULL_VOID(context);
5633 context->AddAfterRenderTask([weak = WeakClaim(this), inspectorId = id]() {
5634 auto host = weak.Upgrade();
5635 CHECK_NULL_VOID(host);
5636 auto pageUrl = Recorder::GetPageUrlByNode(host);
5637 host->exposureProcessor_ = MakeRefPtr<Recorder::ExposureProcessor>(pageUrl, inspectorId);
5638 if (!host->exposureProcessor_->IsNeedRecord()) {
5639 return;
5640 }
5641 host->RecordExposureInner();
5642 });
5643 }
5644 }
5645
OnAutoEventParamUpdate(const std::string & value)5646 void FrameNode::OnAutoEventParamUpdate(const std::string& value)
5647 {
5648 if (value.empty()) {
5649 return;
5650 }
5651 auto paramJson = JsonUtil::ParseJsonString(value);
5652 if (paramJson == nullptr || !paramJson->IsValid() || !paramJson->IsObject()) {
5653 return;
5654 }
5655 if (paramJson->Contains(Recorder::ORIGIN_PARAM)) {
5656 propAutoEventParam_ = paramJson->GetValue(Recorder::ORIGIN_PARAM)->ToString();
5657 }
5658 if (exposureProcessor_ && exposureProcessor_->isListening()) {
5659 return;
5660 }
5661 if (!paramJson->Contains(Recorder::EXPOSURE_CONFIG_PARAM)) {
5662 return;
5663 }
5664 auto exposureCfg = paramJson->GetValue(Recorder::EXPOSURE_CONFIG_PARAM);
5665 if (exposureCfg && exposureCfg->IsObject()) {
5666 auto ratio = exposureCfg->GetDouble(Recorder::EXPOSURE_CONFIG_RATIO);
5667 auto duration = exposureCfg->GetInt(Recorder::EXPOSURE_CONFIG_DURATION);
5668 if (duration <= 0) {
5669 return;
5670 }
5671 auto* context = GetContext();
5672 CHECK_NULL_VOID(context);
5673 context->AddAfterRenderTask([weak = WeakClaim(this), ratio, duration]() {
5674 auto host = weak.Upgrade();
5675 CHECK_NULL_VOID(host);
5676 if (host->exposureProcessor_ && host->exposureProcessor_->isListening()) {
5677 return;
5678 }
5679 auto pageUrl = Recorder::GetPageUrlByNode(host);
5680 host->exposureProcessor_ =
5681 MakeRefPtr<Recorder::ExposureProcessor>(pageUrl, host->GetInspectorIdValue(""), ratio, duration);
5682 if (!host->exposureProcessor_->IsNeedRecord()) {
5683 return;
5684 }
5685 host->RecordExposureInner();
5686 });
5687 }
5688 }
5689
SetExposureProcessor(const RefPtr<Recorder::ExposureProcessor> & processor)5690 void FrameNode::SetExposureProcessor(const RefPtr<Recorder::ExposureProcessor>& processor)
5691 {
5692 if (exposureProcessor_ && exposureProcessor_->isListening()) {
5693 return;
5694 } else {
5695 exposureProcessor_ = MakeRefPtr<Recorder::ExposureProcessor>(processor);
5696 exposureProcessor_->SetContainerId(processor->GetContainerId());
5697 }
5698 exposureProcessor_->OnVisibleChange(true, "");
5699 RecordExposureInner();
5700 }
5701
RecordExposureInner()5702 void FrameNode::RecordExposureInner()
5703 {
5704 auto pipeline = GetContext();
5705 if (!pipeline) {
5706 auto piplineRef = PipelineContext::GetContextByContainerId(exposureProcessor_->GetContainerId());
5707 if (!piplineRef) {
5708 pipeline = Referenced::RawPtr(piplineRef);
5709 }
5710 }
5711 CHECK_NULL_VOID(pipeline);
5712 auto callback = [weak = WeakClaim(RawPtr(exposureProcessor_)), weakNode = WeakClaim(this)](
5713 bool visible, double ratio) {
5714 auto processor = weak.Upgrade();
5715 CHECK_NULL_VOID(processor);
5716 if (!visible) {
5717 auto host = weakNode.Upgrade();
5718 auto param = host ? host->GetAutoEventParamValue("") : "";
5719 processor->OnVisibleChange(false, param);
5720 } else {
5721 processor->OnVisibleChange(visible);
5722 }
5723 };
5724 std::vector<double> ratios = { exposureProcessor_->GetRatio() };
5725 pipeline->AddVisibleAreaChangeNode(Claim(this), ratios, callback, false);
5726 exposureProcessor_->SetListenState(true);
5727 }
5728
AddFrameNodeSnapshot(bool isHit,int32_t parentId,const std::vector<RectF> & responseRegionList,EventTreeType type)5729 void FrameNode::AddFrameNodeSnapshot(
5730 bool isHit, int32_t parentId, const std::vector<RectF>& responseRegionList, EventTreeType type)
5731 {
5732 auto context = GetContext();
5733 CHECK_NULL_VOID(context);
5734 auto eventMgr = context->GetEventManager();
5735 CHECK_NULL_VOID(eventMgr);
5736
5737 FrameNodeSnapshot info = { .nodeId = nodeId_,
5738 .parentNodeId = parentId,
5739 .tag = tag_,
5740 .comId = propInspectorId_.value_or(""),
5741 .monopolizeEvents = GetMonopolizeEvents(),
5742 .isHit = isHit,
5743 .hitTestMode = static_cast<int32_t>(GetHitTestMode()),
5744 .responseRegionList = responseRegionList,
5745 .active = isActive_ };
5746 eventMgr->GetEventTreeRecord(type).AddFrameNodeSnapshot(std::move(info));
5747 }
5748
GetUiExtensionId()5749 int32_t FrameNode::GetUiExtensionId()
5750 {
5751 if (pattern_) {
5752 return pattern_->GetUiExtensionId();
5753 }
5754 return -1;
5755 }
5756
WrapExtensionAbilityId(int64_t extensionOffset,int64_t abilityId)5757 int64_t FrameNode::WrapExtensionAbilityId(int64_t extensionOffset, int64_t abilityId)
5758 {
5759 if (pattern_) {
5760 return pattern_->WrapExtensionAbilityId(extensionOffset, abilityId);
5761 }
5762 return -1;
5763 }
5764
SearchExtensionElementInfoByAccessibilityIdNG(int64_t elementId,int32_t mode,int64_t offset,std::list<Accessibility::AccessibilityElementInfo> & output)5765 void FrameNode::SearchExtensionElementInfoByAccessibilityIdNG(
5766 int64_t elementId, int32_t mode, int64_t offset, std::list<Accessibility::AccessibilityElementInfo>& output)
5767 {
5768 if (pattern_) {
5769 pattern_->SearchExtensionElementInfoByAccessibilityId(elementId, mode, offset, output);
5770 }
5771 }
5772
SearchElementInfosByTextNG(int64_t elementId,const std::string & text,int64_t offset,std::list<Accessibility::AccessibilityElementInfo> & output)5773 void FrameNode::SearchElementInfosByTextNG(int64_t elementId, const std::string& text, int64_t offset,
5774 std::list<Accessibility::AccessibilityElementInfo>& output)
5775 {
5776 if (pattern_) {
5777 pattern_->SearchElementInfosByText(elementId, text, offset, output);
5778 }
5779 }
5780
FindFocusedExtensionElementInfoNG(int64_t elementId,int32_t focusType,int64_t offset,Accessibility::AccessibilityElementInfo & output)5781 void FrameNode::FindFocusedExtensionElementInfoNG(
5782 int64_t elementId, int32_t focusType, int64_t offset, Accessibility::AccessibilityElementInfo& output)
5783 {
5784 if (pattern_) {
5785 pattern_->FindFocusedElementInfo(elementId, focusType, offset, output);
5786 }
5787 }
5788
FocusMoveSearchNG(int64_t elementId,int32_t direction,int64_t offset,Accessibility::AccessibilityElementInfo & output)5789 void FrameNode::FocusMoveSearchNG(
5790 int64_t elementId, int32_t direction, int64_t offset, Accessibility::AccessibilityElementInfo& output)
5791 {
5792 if (pattern_) {
5793 pattern_->FocusMoveSearch(elementId, direction, offset, output);
5794 }
5795 }
5796
TransferExecuteAction(int64_t elementId,const std::map<std::string,std::string> & actionArguments,int32_t action,int64_t offset)5797 bool FrameNode::TransferExecuteAction(
5798 int64_t elementId, const std::map<std::string, std::string>& actionArguments, int32_t action, int64_t offset)
5799 {
5800 bool isExecuted = false;
5801 if (pattern_) {
5802 isExecuted = pattern_->TransferExecuteAction(elementId, actionArguments, action, offset);
5803 }
5804 return isExecuted;
5805 }
5806
GetOnChildTouchTestRet(const std::vector<TouchTestInfo> & touchInfo)5807 TouchResult FrameNode::GetOnChildTouchTestRet(const std::vector<TouchTestInfo>& touchInfo)
5808 {
5809 TouchResult res;
5810 res.strategy = TouchTestStrategy::DEFAULT;
5811
5812 auto func = GetOnTouchTestFunc();
5813 if (func == nullptr) {
5814 return res;
5815 }
5816 return func(touchInfo);
5817 }
5818
GetOnTouchTestFunc()5819 OnChildTouchTestFunc FrameNode::GetOnTouchTestFunc()
5820 {
5821 auto gestureHub = eventHub_ ? eventHub_->GetGestureEventHub() : nullptr;
5822 if (gestureHub == nullptr) {
5823 return nullptr;
5824 }
5825 auto& func = gestureHub->GetOnTouchTestFunc();
5826 return func;
5827 }
5828
CollectTouchInfos(const PointF & globalPoint,const PointF & parentRevertPoint,std::vector<TouchTestInfo> & touchInfos)5829 void FrameNode::CollectTouchInfos(
5830 const PointF& globalPoint, const PointF& parentRevertPoint, std::vector<TouchTestInfo>& touchInfos)
5831 {
5832 if (GetOnTouchTestFunc() == nullptr) {
5833 return;
5834 }
5835
5836 for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
5837 const auto& child = iter->Upgrade();
5838 if (!child) {
5839 continue;
5840 }
5841
5842 TouchTestInfo info;
5843 if (!child->GetInspectorId().has_value()) {
5844 continue;
5845 }
5846 info.id = child->GetInspectorId().value();
5847 info.windowPoint = globalPoint;
5848 info.currentCmpPoint = parentRevertPoint;
5849
5850 auto renderContext = child->GetRenderContext();
5851 CHECK_NULL_VOID(renderContext);
5852 auto origRect = renderContext->GetPaintRectWithoutTransform();
5853 auto revertPoint = parentRevertPoint;
5854 renderContext->GetPointWithRevert(revertPoint);
5855 auto subRevertPoint = revertPoint - origRect.GetOffset();
5856 info.subCmpPoint = subRevertPoint;
5857
5858 info.subRect = child->GetGeometryNode()->GetFrameRect();
5859
5860 touchInfos.emplace_back(info);
5861 }
5862 }
5863
GetDispatchFrameNode(const TouchResult & touchRes)5864 RefPtr<FrameNode> FrameNode::GetDispatchFrameNode(const TouchResult& touchRes)
5865 {
5866 if (touchRes.strategy != TouchTestStrategy::FORWARD_COMPETITION &&
5867 touchRes.strategy != TouchTestStrategy::FORWARD) {
5868 return nullptr;
5869 }
5870
5871 for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
5872 const auto& child = iter->Upgrade();
5873 if (!child) {
5874 continue;
5875 }
5876 std::string id = child->GetInspectorId().value_or("");
5877 if ((!touchRes.id.empty()) && (touchRes.id == id)) {
5878 return child;
5879 }
5880 }
5881 return nullptr;
5882 }
5883
CalculateCachedTransformRelativeOffset(uint64_t nanoTimestamp)5884 OffsetF FrameNode::CalculateCachedTransformRelativeOffset(uint64_t nanoTimestamp)
5885 {
5886 auto context = GetRenderContext();
5887 CHECK_NULL_RETURN(context, OffsetF());
5888 auto offset = context->GetPaintRectWithTransform().GetOffset();
5889
5890 auto parent = GetAncestorNodeOfFrame(true);
5891 if (parent) {
5892 auto parentTimestampOffset = parent->GetCachedTransformRelativeOffset();
5893 if (parentTimestampOffset.first == nanoTimestamp) {
5894 auto result = offset + parentTimestampOffset.second;
5895 SetCachedTransformRelativeOffset({ nanoTimestamp, result });
5896 return result;
5897 }
5898 auto result = offset + parent->CalculateCachedTransformRelativeOffset(nanoTimestamp);
5899 SetCachedTransformRelativeOffset({ nanoTimestamp, result });
5900 return result;
5901 }
5902 SetCachedTransformRelativeOffset({ nanoTimestamp, offset });
5903 return offset;
5904 }
5905
CalculateOffsetRelativeToWindow(uint64_t nanoTimestamp,bool logFlag,int32_t areaChangeMinDepth)5906 OffsetF FrameNode::CalculateOffsetRelativeToWindow(uint64_t nanoTimestamp, bool logFlag, int32_t areaChangeMinDepth)
5907 {
5908 auto currOffset = GetFrameRectWithSafeArea().GetOffset();
5909 if (renderContext_ && renderContext_->GetPositionProperty()) {
5910 if (renderContext_->GetPositionProperty()->HasPosition()) {
5911 auto renderPosition =
5912 ContextPositionConvertToPX(renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
5913 currOffset.SetX(static_cast<float>(renderPosition.first));
5914 currOffset.SetY(static_cast<float>(renderPosition.second));
5915 }
5916 }
5917
5918 // if this node have not calculate once, then it will calculate to root
5919 areaChangeMinDepth = cachedGlobalOffset_.first > 0 ? areaChangeMinDepth : -1;
5920 auto parent = GetAncestorNodeOfFrame(true);
5921 if (parent) {
5922 auto parentTimestampOffset = parent->GetCachedGlobalOffset();
5923 // MinDepth < 0, it do not work
5924 // MinDepth >= 0, and this node have calculate once
5925 // MinDepth = 0, no change from last frame, use cache directly
5926 // MinDepth > 0, and parent->GetDepth < MinDepth, parent do not change, use cache directly
5927 if ((parentTimestampOffset.first == nanoTimestamp) ||
5928 ((areaChangeMinDepth >= 0) && parentTimestampOffset.first && (areaChangeMinDepth == 0 ||
5929 ((areaChangeMinDepth > 0) && (parent->GetDepth() < areaChangeMinDepth))))) {
5930 currOffset = currOffset + parentTimestampOffset.second;
5931 SetCachedGlobalOffset({ nanoTimestamp, currOffset });
5932 } else {
5933 currOffset = currOffset + parent->CalculateOffsetRelativeToWindow(
5934 nanoTimestamp, logFlag, areaChangeMinDepth);
5935 SetCachedGlobalOffset({ nanoTimestamp, currOffset });
5936 }
5937 } else {
5938 SetCachedGlobalOffset({ nanoTimestamp, currOffset });
5939 }
5940 if (logFlag) {
5941 TAG_LOGD(AceLogTag::ACE_UIEVENT, "OnAreaChange Node(%{public}s/%{public}d) offsetToWindow:%{public}s",
5942 tag_.c_str(), nodeId_, currOffset.ToString().c_str());
5943 }
5944 return currOffset;
5945 }
5946
GetNodeContainer()5947 RefPtr<FrameNode> FrameNode::GetNodeContainer()
5948 {
5949 if (tag_ == V2::NODE_CONTAINER_ETS_TAG) {
5950 return Claim(this);
5951 }
5952 auto parent = GetParent();
5953 while (parent && parent->GetTag() != V2::NODE_CONTAINER_ETS_TAG) {
5954 parent = parent->GetParent();
5955 }
5956 return AceType::DynamicCast<FrameNode>(parent);
5957 }
5958
InitLastArea()5959 void FrameNode::InitLastArea()
5960 {
5961 if (!lastFrameRect_) {
5962 lastFrameRect_ = std::make_unique<RectF>();
5963 }
5964 if (!lastParentOffsetToWindow_) {
5965 lastParentOffsetToWindow_ = std::make_unique<OffsetF>();
5966 }
5967 if (!lastHostParentOffsetToWindow_) {
5968 lastHostParentOffsetToWindow_ = std::make_shared<OffsetF>();
5969 }
5970 }
5971
SetParentLayoutConstraint(const SizeF & size) const5972 bool FrameNode::SetParentLayoutConstraint(const SizeF& size) const
5973 {
5974 LayoutConstraintF layoutConstraint;
5975 layoutConstraint.UpdatePercentReference(size);
5976 layoutConstraint.UpdateMaxSizeWithCheck(size);
5977 layoutConstraint.UpdateIllegalParentIdealSizeWithCheck(OptionalSize(size));
5978 layoutProperty_->UpdateParentLayoutConstraint(layoutConstraint);
5979 return true;
5980 }
5981
ForceSyncGeometryNode()5982 void FrameNode::ForceSyncGeometryNode()
5983 {
5984 CHECK_NULL_VOID(renderContext_);
5985 oldGeometryNode_.Reset();
5986 renderContext_->SavePaintRect();
5987 renderContext_->SyncGeometryProperties(RawPtr(geometryNode_));
5988 }
5989
IsGeometrySizeChange() const5990 bool FrameNode::IsGeometrySizeChange() const
5991 {
5992 if (oldGeometryNode_ && geometryNode_) {
5993 return oldGeometryNode_->GetFrameSize() != geometryNode_->GetFrameSize();
5994 }
5995 return false;
5996 }
5997
GetCachedGlobalOffset() const5998 const std::pair<uint64_t, OffsetF>& FrameNode::GetCachedGlobalOffset() const
5999 {
6000 return cachedGlobalOffset_;
6001 }
6002
SetCachedGlobalOffset(const std::pair<uint64_t,OffsetF> & timestampOffset)6003 void FrameNode::SetCachedGlobalOffset(const std::pair<uint64_t, OffsetF>& timestampOffset)
6004 {
6005 cachedGlobalOffset_ = timestampOffset;
6006 }
GetCachedTransformRelativeOffset() const6007 const std::pair<uint64_t, OffsetF>& FrameNode::GetCachedTransformRelativeOffset() const
6008 {
6009 return cachedTransformRelativeOffset_;
6010 }
6011
SetCachedTransformRelativeOffset(const std::pair<uint64_t,OffsetF> & timestampOffset)6012 void FrameNode::SetCachedTransformRelativeOffset(const std::pair<uint64_t, OffsetF>& timestampOffset)
6013 {
6014 cachedTransformRelativeOffset_ = timestampOffset;
6015 }
6016
PaintDebugBoundary(bool flag)6017 void FrameNode::PaintDebugBoundary(bool flag)
6018 {
6019 if (!isActive_) {
6020 return;
6021 }
6022 if (renderContext_) {
6023 renderContext_->PaintDebugBoundary(flag);
6024 }
6025 }
6026
SetChangeInfo(const TouchEvent & touchEvent,TouchLocationInfo & changedInfo)6027 void SetChangeInfo(const TouchEvent& touchEvent, TouchLocationInfo &changedInfo)
6028 {
6029 changedInfo.SetGlobalLocation(Offset(touchEvent.x, touchEvent.y));
6030 changedInfo.SetScreenLocation(Offset(touchEvent.screenX, touchEvent.screenY));
6031 changedInfo.SetGlobalDisplayLocation(Offset(touchEvent.globalDisplayX, touchEvent.globalDisplayY));
6032 changedInfo.SetTouchType(touchEvent.type);
6033 changedInfo.SetForce(touchEvent.force);
6034 changedInfo.SetPressedTime(touchEvent.pressedTime);
6035 changedInfo.SetWidth(touchEvent.width);
6036 changedInfo.SetHeight(touchEvent.height);
6037 if (touchEvent.tiltX.has_value()) {
6038 changedInfo.SetTiltX(touchEvent.tiltX.value());
6039 }
6040 if (touchEvent.tiltY.has_value()) {
6041 changedInfo.SetTiltY(touchEvent.tiltY.value());
6042 }
6043 changedInfo.SetSourceTool(touchEvent.sourceTool);
6044 changedInfo.SetDeviceId(touchEvent.deviceId);
6045 }
6046
TriggerOnTouchIntercept(const TouchEvent & touchEvent)6047 HitTestMode FrameNode::TriggerOnTouchIntercept(const TouchEvent& touchEvent)
6048 {
6049 auto gestureHub = eventHub_ ? eventHub_->GetGestureEventHub() : nullptr;
6050 CHECK_NULL_RETURN(gestureHub, HitTestMode::HTMDEFAULT);
6051 auto onTouchIntercept = gestureHub->GetOnTouchIntercept();
6052 CHECK_NULL_RETURN(onTouchIntercept, HitTestMode::HTMDEFAULT);
6053 TouchEventInfo event("touchEvent");
6054 event.SetTimeStamp(touchEvent.time);
6055 event.SetDeviceId(touchEvent.deviceId);
6056 event.SetPointerEvent(touchEvent.GetTouchEventPointerEvent());
6057 TouchLocationInfo changedInfo("onTouch", touchEvent.originalId);
6058 PointF lastLocalPoint(touchEvent.x, touchEvent.y);
6059 NGGestureRecognizer::Transform(lastLocalPoint, Claim(this), false, false);
6060 auto localX = static_cast<float>(lastLocalPoint.GetX());
6061 auto localY = static_cast<float>(lastLocalPoint.GetY());
6062 changedInfo.SetLocalLocation(Offset(localX, localY));
6063 SetChangeInfo(touchEvent, changedInfo);
6064 event.AddChangedTouchLocationInfo(std::move(changedInfo));
6065
6066 AddTouchEventAllFingersInfo(event, touchEvent);
6067 event.SetSourceDevice(touchEvent.sourceType);
6068 event.SetForce(touchEvent.force);
6069 if (touchEvent.tiltX.has_value()) {
6070 event.SetTiltX(touchEvent.tiltX.value());
6071 }
6072 if (touchEvent.tiltY.has_value()) {
6073 event.SetTiltY(touchEvent.tiltY.value());
6074 }
6075 if (touchEvent.rollAngle.has_value()) {
6076 event.SetRollAngle(touchEvent.rollAngle.value());
6077 }
6078 event.SetSourceTool(touchEvent.sourceTool);
6079 EventTarget eventTarget;
6080 eventTarget.id = GetInspectorId().value_or("").c_str();
6081 event.SetTarget(eventTarget);
6082 event.SetPressedKeyCodes(touchEvent.pressedKeyCodes_);
6083 event.SetTargetDisplayId(touchEvent.targetDisplayId);
6084 auto result = onTouchIntercept(event);
6085 SetHitTestMode(result);
6086 return result;
6087 }
6088
AddTouchEventAllFingersInfo(TouchEventInfo & event,const TouchEvent & touchEvent)6089 void FrameNode::AddTouchEventAllFingersInfo(TouchEventInfo& event, const TouchEvent& touchEvent)
6090 {
6091 // all fingers collection
6092 for (const auto& item : touchEvent.pointers) {
6093 float globalX = item.x;
6094 float globalY = item.y;
6095 float screenX = item.screenX;
6096 float screenY = item.screenY;
6097 double globalDisplayX = item.globalDisplayX;
6098 double globalDisplayY = item.globalDisplayY;
6099 PointF localPoint(globalX, globalY);
6100 NGGestureRecognizer::Transform(localPoint, Claim(this), false, false);
6101 auto localX = static_cast<float>(localPoint.GetX());
6102 auto localY = static_cast<float>(localPoint.GetY());
6103 TouchLocationInfo info("onTouch", item.originalId);
6104 info.SetGlobalLocation(Offset(globalX, globalY));
6105 info.SetLocalLocation(Offset(localX, localY));
6106 info.SetScreenLocation(Offset(screenX, screenY));
6107 info.SetGlobalDisplayLocation(Offset(globalDisplayX, globalDisplayY));
6108 info.SetTouchType(touchEvent.type);
6109 info.SetForce(item.force);
6110 info.SetPressedTime(item.downTime);
6111 info.SetWidth(item.width);
6112 info.SetHeight(item.height);
6113 if (item.tiltX.has_value()) {
6114 info.SetTiltX(item.tiltX.value());
6115 }
6116 if (item.tiltY.has_value()) {
6117 info.SetTiltY(item.tiltY.value());
6118 }
6119 info.SetSourceTool(item.sourceTool);
6120 event.AddTouchLocationInfo(std::move(info));
6121 }
6122 }
6123
ChangeSensitiveStyle(bool isSensitive)6124 void FrameNode::ChangeSensitiveStyle(bool isSensitive)
6125 {
6126 pattern_->OnSensitiveStyleChange(isSensitive);
6127 }
6128
AttachContext(PipelineContext * context,bool recursive)6129 void FrameNode::AttachContext(PipelineContext* context, bool recursive)
6130 {
6131 if (SystemProperties::GetMultiInstanceEnabled()) {
6132 auto renderContext = GetRenderContext();
6133 if (!isDeleteRsNode_ && renderContext) {
6134 renderContext->SetRSUIContext(context);
6135 }
6136 }
6137 UINode::AttachContext(context, recursive);
6138 if (eventHub_) {
6139 eventHub_->OnAttachContext(context);
6140 }
6141 pattern_->OnAttachContext(context);
6142 }
6143
DetachContext(bool recursive)6144 void FrameNode::DetachContext(bool recursive)
6145 {
6146 CHECK_NULL_VOID(context_);
6147 pattern_->OnDetachContext(context_);
6148 if (eventHub_) {
6149 eventHub_->OnDetachContext(context_);
6150 }
6151 UINode::DetachContext(recursive);
6152 }
6153
OnCollectRemoved()6154 void FrameNode::OnCollectRemoved()
6155 {
6156 pattern_->OnCollectRemoved();
6157 }
6158
ApplyFrameNodeTranformToRect(const RectF & rect,const RefPtr<FrameNode> & parent) const6159 RectF FrameNode::ApplyFrameNodeTranformToRect(const RectF& rect, const RefPtr<FrameNode>& parent) const
6160 {
6161 RectF newRect = rect;
6162 if (!parent) {
6163 return newRect;
6164 }
6165
6166 auto parentRenderContext = parent->GetRenderContext();
6167 if (!parentRenderContext) {
6168 return newRect;
6169 }
6170
6171 auto parentScale = parentRenderContext->GetTransformScale();
6172 auto offset = rect.GetOffset();
6173 if (parentScale) {
6174 newRect.SetWidth(rect.Width() * parentScale.value().x);
6175 newRect.SetHeight(rect.Height() * parentScale.value().y);
6176 offset = OffsetF(offset.GetX() * parentScale.value().x, offset.GetY() * parentScale.value().y);
6177 }
6178 offset += parentRenderContext->GetPaintRectWithTransform().GetOffset();
6179 newRect.SetOffset(offset);
6180 return newRect;
6181 }
6182
GetVisibleRect(RectF & visibleRect,RectF & frameRect) const6183 void FrameNode::GetVisibleRect(RectF& visibleRect, RectF& frameRect) const
6184 {
6185 visibleRect = GetPaintRectWithTransform();
6186 frameRect = visibleRect;
6187 RefPtr<FrameNode> parentUi = GetAncestorNodeOfFrame(true);
6188 if (!parentUi) {
6189 visibleRect.SetWidth(0.0f);
6190 visibleRect.SetHeight(0.0f);
6191 return;
6192 }
6193 while (parentUi) {
6194 visibleRect = ApplyFrameNodeTranformToRect(visibleRect, parentUi);
6195 auto parentRect = parentUi->GetPaintRectWithTransform();
6196 visibleRect = visibleRect.Constrain(parentRect);
6197 if (visibleRect.IsEmpty()) {
6198 return;
6199 }
6200 frameRect = ApplyFrameNodeTranformToRect(frameRect, parentUi);
6201 parentUi = parentUi->GetAncestorNodeOfFrame(true);
6202 }
6203 }
6204
AllowVisibleAreaCheck() const6205 bool FrameNode::AllowVisibleAreaCheck() const
6206 {
6207 return IsOnMainTree() || (pattern_ && pattern_->AllowVisibleAreaCheck());
6208 }
6209
GetVisibleRectWithClip(RectF & visibleRect,RectF & visibleInnerRect,RectF & frameRect) const6210 void FrameNode::GetVisibleRectWithClip(RectF& visibleRect, RectF& visibleInnerRect, RectF& frameRect) const
6211 {
6212 visibleRect = GetPaintRectWithTransform();
6213 frameRect = visibleRect;
6214 visibleInnerRect = visibleRect;
6215 RefPtr<FrameNode> parentUi = GetAncestorNodeOfFrame(true);
6216 if (!AllowVisibleAreaCheck() || !parentUi || IsFrameDisappear()) {
6217 visibleRect.SetWidth(0.0f);
6218 visibleRect.SetHeight(0.0f);
6219 visibleInnerRect.SetWidth(0.0f);
6220 visibleInnerRect.SetHeight(0.0f);
6221 return;
6222 }
6223
6224 while (parentUi) {
6225 visibleRect = ApplyFrameNodeTranformToRect(visibleRect, parentUi);
6226 auto parentRect = parentUi->GetPaintRectWithTransform();
6227 if (!visibleRect.IsEmpty()) {
6228 visibleRect = visibleRect.Constrain(parentRect);
6229 }
6230
6231 if (isCalculateInnerVisibleRectClip_) {
6232 visibleInnerRect = ApplyFrameNodeTranformToRect(visibleInnerRect, parentUi);
6233 auto parentContext = parentUi->GetRenderContext();
6234 if (!visibleInnerRect.IsEmpty() && ((parentContext && parentContext->GetClipEdge().value_or(false)) ||
6235 parentUi->IsWindowBoundary() || parentUi->GetTag() == V2::ROOT_ETS_TAG)) {
6236 visibleInnerRect = visibleInnerRect.Constrain(parentRect);
6237 }
6238 }
6239
6240 if (visibleRect.IsEmpty() && (!isCalculateInnerVisibleRectClip_ || visibleInnerRect.IsEmpty())) {
6241 visibleInnerRect = visibleRect;
6242 return;
6243 }
6244 frameRect = ApplyFrameNodeTranformToRect(frameRect, parentUi);
6245 parentUi = parentUi->GetAncestorNodeOfFrame(true);
6246 }
6247
6248 if (!isCalculateInnerVisibleRectClip_) {
6249 visibleInnerRect = visibleRect;
6250 }
6251 }
6252
GetCacheVisibleRect(uint64_t timestamp,bool logFlag)6253 CacheVisibleRectResult FrameNode::GetCacheVisibleRect(uint64_t timestamp, bool logFlag)
6254 {
6255 RefPtr<FrameNode> parentUi = GetAncestorNodeOfFrame(true);
6256 auto rectToParent = GetPaintRectWithTransform();
6257 auto scale = GetTransformScale();
6258 auto innerScale = scale;
6259 if (renderContext_) {
6260 auto matrix4 = renderContext_->GetTransformMatrixValue(Matrix4());
6261 innerScale = { innerScale.x * static_cast<float>(matrix4.GetScaleX()),
6262 innerScale.y * static_cast<float>(matrix4.GetScaleY()) };
6263 }
6264
6265 if (!parentUi || IsWindowBoundary()) {
6266 cachedVisibleRectResult_ = { timestamp,
6267 { rectToParent.GetOffset(), rectToParent.GetOffset(), rectToParent, rectToParent, scale, innerScale,
6268 rectToParent, rectToParent, rectToParent } };
6269 return cachedVisibleRectResult_.second;
6270 }
6271
6272 CacheVisibleRectResult result;
6273 if (parentUi->cachedVisibleRectResult_.first == timestamp) {
6274 auto parentCacheVisibleRectResult = parentUi->cachedVisibleRectResult_.second;
6275 result = CalculateCacheVisibleRect(
6276 parentCacheVisibleRectResult, parentUi, rectToParent, { scale, innerScale }, timestamp);
6277 } else {
6278 CacheVisibleRectResult parentCacheVisibleRectResult = parentUi->GetCacheVisibleRect(timestamp, logFlag);
6279 result = CalculateCacheVisibleRect(
6280 parentCacheVisibleRectResult, parentUi, rectToParent, { scale, innerScale }, timestamp);
6281 }
6282 if (logFlag) {
6283 TAG_LOGD(AceLogTag::ACE_UIEVENT,
6284 "OnVisibleAreaChange Node(%{public}s/%{public}d) windowOffset:%{public}s visibleRect:%{public}s "
6285 "innerVisibleRect:%{public}s frameRect:%{public}s innerBoundaryRect:%{public}s",
6286 tag_.c_str(), nodeId_, result.windowOffset.ToString().c_str(), result.visibleRect.ToString().c_str(),
6287 result.innerVisibleRect.ToString().c_str(), result.frameRect.ToString().c_str(),
6288 result.innerBoundaryRect.ToString().c_str());
6289 }
6290 return result;
6291 }
6292
CalculateCacheVisibleRect(CacheVisibleRectResult & parentCacheVisibleRect,const RefPtr<FrameNode> & parentUi,RectF & rectToParent,const std::pair<VectorF,VectorF> & pairScale,uint64_t timestamp)6293 CacheVisibleRectResult FrameNode::CalculateCacheVisibleRect(CacheVisibleRectResult& parentCacheVisibleRect,
6294 const RefPtr<FrameNode>& parentUi, RectF& rectToParent, const std::pair<VectorF, VectorF>& pairScale,
6295 uint64_t timestamp)
6296 {
6297 auto parentRenderContext = parentUi->GetRenderContext();
6298 OffsetF windowOffset;
6299 OffsetF innerWindowOffset;
6300 auto offset = rectToParent.GetOffset();
6301 auto innerOffset = rectToParent.GetOffset();
6302 if (parentRenderContext && parentRenderContext->GetTransformScale()) {
6303 auto parentScale = parentRenderContext->GetTransformScale();
6304 offset = OffsetF(offset.GetX() * parentScale.value().x, offset.GetY() * parentScale.value().y);
6305 }
6306 windowOffset = parentCacheVisibleRect.windowOffset + offset;
6307
6308 innerOffset = OffsetF(innerOffset.GetX() * parentCacheVisibleRect.innerCumulativeScale.x,
6309 innerOffset.GetY() * parentCacheVisibleRect.innerCumulativeScale.y);
6310 innerWindowOffset = parentCacheVisibleRect.innerWindowOffset + innerOffset;
6311
6312 RectF rect;
6313 rect.SetOffset(windowOffset);
6314 rect.SetWidth(rectToParent.Width() * parentCacheVisibleRect.cumulativeScale.x);
6315 rect.SetHeight(rectToParent.Height() * parentCacheVisibleRect.cumulativeScale.y);
6316
6317 RectF innerRect;
6318 innerRect.SetOffset(innerWindowOffset);
6319 innerRect.SetWidth(rectToParent.Width() * parentCacheVisibleRect.innerCumulativeScale.x);
6320 innerRect.SetHeight(rectToParent.Height() * parentCacheVisibleRect.innerCumulativeScale.y);
6321
6322 auto visibleRect = rect.Constrain(parentCacheVisibleRect.visibleRect);
6323 auto innerVisibleRect = innerRect;
6324 auto innerBoundaryRect = parentCacheVisibleRect.innerBoundaryRect;
6325 if (parentRenderContext && parentRenderContext->GetClipEdge().value_or(false)) {
6326 innerBoundaryRect = parentCacheVisibleRect.innerVisibleRect.Constrain(innerBoundaryRect);
6327 }
6328 innerVisibleRect = innerRect.Constrain(innerBoundaryRect);
6329
6330 VectorF cumulativeScale = { pairScale.first.x * parentCacheVisibleRect.cumulativeScale.x,
6331 pairScale.first.y * parentCacheVisibleRect.cumulativeScale.y };
6332 VectorF innerCumulativeScale = { pairScale.second.x * parentCacheVisibleRect.innerCumulativeScale.x,
6333 pairScale.second.y * parentCacheVisibleRect.innerCumulativeScale.y };
6334 cachedVisibleRectResult_ = { timestamp,
6335 { windowOffset, innerWindowOffset, visibleRect, innerVisibleRect, cumulativeScale, innerCumulativeScale, rect,
6336 innerRect, innerBoundaryRect } };
6337 return { windowOffset, innerWindowOffset, visibleRect, innerVisibleRect, cumulativeScale, innerCumulativeScale,
6338 rect, innerRect, innerBoundaryRect };
6339 }
6340
IsContextTransparent()6341 bool FrameNode::IsContextTransparent()
6342 {
6343 ACE_SCOPED_TRACE("Transparent detection");
6344 const auto& rect = renderContext_->GetPaintRectWithTransform();
6345 auto width = rect.Width();
6346 auto height = rect.Height();
6347 if (renderContext_->GetOpacity().has_value() && renderContext_->GetOpacity().value() <= MIN_OPACITY) {
6348 return true;
6349 }
6350 auto layoutTags = GetLayoutTags();
6351 if (layoutTags.find(tag_) == layoutTags.end()) {
6352 if (width > MIN_WIDTH && height > MIN_HEIGHT &&
6353 static_cast<int32_t>(layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)) == 0) {
6354 return false;
6355 }
6356 } else {
6357 if (width > MIN_WIDTH && height > MIN_HEIGHT &&
6358 static_cast<int32_t>(layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)) == 0 &&
6359 renderContext_->GetBackgroundColor()->ColorToString().compare("#00000000") != 0) {
6360 return false;
6361 }
6362 }
6363 for (const auto& item : GetChildren()) {
6364 if (!item->IsContextTransparent()) {
6365 return false;
6366 }
6367 }
6368 return true;
6369 }
6370
GetOrRefreshMatrixFromCache(bool forceRefresh)6371 CacheMatrixInfo& FrameNode::GetOrRefreshMatrixFromCache(bool forceRefresh)
6372 {
6373 auto pipeline = GetContext();
6374 CHECK_NULL_RETURN(pipeline, cacheMatrixInfo_);
6375 auto nanoTimestamp = pipeline->GetVsyncTime();
6376 CHECK_NULL_RETURN(renderContext_, cacheMatrixInfo_);
6377 auto rect = renderContext_->GetPaintRectWithoutTransform();
6378 // the caller is trying to refresh cache forcedly or the cache is invalid
6379 if (!isTransformNotChanged_ || forceRefresh || prePaintRect_ != rect ||
6380 getCacheNanoTime_ + MATRIX_CACHE_TIME_THRESHOLD < nanoTimestamp) {
6381 cacheMatrixInfo_.revertMatrix = renderContext_->GetRevertMatrix();
6382 cacheMatrixInfo_.paintRectWithTransform = renderContext_->GetPaintRectWithTransform();
6383 cacheMatrixInfo_.localMatrix = Matrix4::CreateTranslate(-rect.GetOffset().GetX(),
6384 -rect.GetOffset().GetY(), 0) * cacheMatrixInfo_.revertMatrix;
6385 isTransformNotChanged_ = true;
6386 getCacheNanoTime_ = nanoTimestamp;
6387 prePaintRect_ = rect;
6388 return cacheMatrixInfo_;
6389 }
6390
6391 // cache valid
6392 return cacheMatrixInfo_;
6393 }
6394
6395 // apply the matrix to the given point specified by dst
MapPointTo(PointF & dst,Matrix4 & matrix)6396 void FrameNode::MapPointTo(PointF& dst, Matrix4& matrix)
6397 {
6398 Point tmp(dst.GetX(), dst.GetY());
6399 auto transformPoint = matrix * tmp;
6400 dst.SetX(transformPoint.GetX());
6401 dst.SetY(transformPoint.GetY());
6402 }
6403
SetSuggestOpIncMarked(bool flag)6404 void FrameNode::SetSuggestOpIncMarked(bool flag)
6405 {
6406 if (flag) {
6407 suggestOpIncByte_ |= SUGGEST_OPINC_MARKED_MASK;
6408 } else {
6409 suggestOpIncByte_ &= (~SUGGEST_OPINC_MARKED_MASK);
6410 }
6411 }
6412
GetSuggestOpIncMarked()6413 bool FrameNode::GetSuggestOpIncMarked()
6414 {
6415 return (suggestOpIncByte_ & SUGGEST_OPINC_MARKED_MASK) > 0;
6416 }
6417
SetCanSuggestOpInc(bool flag)6418 void FrameNode::SetCanSuggestOpInc(bool flag)
6419 {
6420 if (flag) {
6421 suggestOpIncByte_ |= CAN_SUGGEST_OPINC_MASK;
6422 } else {
6423 suggestOpIncByte_ &= (~CAN_SUGGEST_OPINC_MASK);
6424 }
6425 }
6426
GetCanSuggestOpInc()6427 bool FrameNode::GetCanSuggestOpInc()
6428 {
6429 return (suggestOpIncByte_ & CAN_SUGGEST_OPINC_MASK) > 0;
6430 }
6431
SetApplicationRenderGroupMarked(bool flag)6432 void FrameNode::SetApplicationRenderGroupMarked(bool flag)
6433 {
6434 if (flag) {
6435 suggestOpIncByte_ |= APP_RENDER_GROUP_MARKED_MASK;
6436 } else {
6437 suggestOpIncByte_ &= (~APP_RENDER_GROUP_MARKED_MASK);
6438 }
6439 }
6440
GetApplicationRenderGroupMarked()6441 bool FrameNode::GetApplicationRenderGroupMarked()
6442 {
6443 return (suggestOpIncByte_ & APP_RENDER_GROUP_MARKED_MASK) > 0;
6444 }
6445
SetSuggestOpIncActivatedOnce()6446 void FrameNode::SetSuggestOpIncActivatedOnce()
6447 {
6448 suggestOpIncByte_ |= SUGGEST_OPINC_ACTIVATED_ONCE;
6449 }
6450
GetSuggestOpIncActivatedOnce()6451 bool FrameNode::GetSuggestOpIncActivatedOnce()
6452 {
6453 return (suggestOpIncByte_ & SUGGEST_OPINC_ACTIVATED_ONCE) > 0;
6454 }
6455
SetOpIncGroupCheckedThrough(bool flag)6456 void FrameNode::SetOpIncGroupCheckedThrough(bool flag)
6457 {
6458 if (flag) {
6459 suggestOpIncByte_ |= SUGGEST_OPINC_CHECKED_THROUGH;
6460 } else {
6461 suggestOpIncByte_ &= (~SUGGEST_OPINC_CHECKED_THROUGH);
6462 }
6463 }
6464
GetOpIncGroupCheckedThrough()6465 bool FrameNode::GetOpIncGroupCheckedThrough()
6466 {
6467 return (suggestOpIncByte_ & SUGGEST_OPINC_CHECKED_THROUGH) > 0;
6468 }
6469
SetOpIncCheckedOnce()6470 void FrameNode::SetOpIncCheckedOnce()
6471 {
6472 suggestOpIncByte_ |= SUGGEST_OPINC_CHCKED_ONCE;
6473 }
GetOpIncCheckedOnce()6474 bool FrameNode::GetOpIncCheckedOnce()
6475 {
6476 return (suggestOpIncByte_ & SUGGEST_OPINC_CHCKED_ONCE) > 0;
6477 }
6478
MarkSuggestOpIncGroup(bool suggest,bool calc)6479 bool FrameNode::MarkSuggestOpIncGroup(bool suggest, bool calc)
6480 {
6481 CHECK_NULL_RETURN(renderContext_, false);
6482 renderContext_->SuggestOpIncNode(suggest, calc);
6483 SetSuggestOpIncMarked(suggest);
6484 return true;
6485 }
6486
IsOpIncValidNode(const SizeF & boundary,Axis axis,int32_t childNumber)6487 OPINC_TYPE_E FrameNode::IsOpIncValidNode(const SizeF& boundary, Axis axis, int32_t childNumber)
6488 {
6489 int32_t height = static_cast<int>(GetGeometryNode()->GetFrameSize().Height());
6490 int32_t width = static_cast<int>(GetGeometryNode()->GetFrameSize().Width());
6491 int32_t heightBoundary = static_cast<int>(boundary.Height() * HIGHT_RATIO_LIMIT);
6492 int32_t widthBoundary = static_cast<int>(boundary.Width() * WIDTH_RATIO_LIMIT);
6493 int32_t area = height * width;
6494 if (area >= MIN_OPINC_AREA &&
6495 ((axis == Axis::VERTICAL && height <= heightBoundary) ||
6496 (axis == Axis::HORIZONTAL && width <= widthBoundary)) &&
6497 HasMultipleChild()) {
6498 return OPINC_NODE;
6499 }
6500 return OPINC_INVALID;
6501 }
6502
HasMultipleChild()6503 bool FrameNode::HasMultipleChild()
6504 {
6505 if (GetChildren().empty()) {
6506 return false;
6507 }
6508 if (GetChildren().size() > 1) {
6509 return true;
6510 }
6511 auto child = AceType::DynamicCast<FrameNode>(GetChildByIndex(0));
6512 CHECK_NULL_RETURN(child, false);
6513 return child->HasMultipleChild();
6514 }
6515
FindSuggestOpIncNode(std::string & path,const SizeF & boundary,int32_t depth,Axis axis)6516 OPINC_TYPE_E FrameNode::FindSuggestOpIncNode(std::string& path, const SizeF& boundary, int32_t depth, Axis axis)
6517 {
6518 if (GetSuggestOpIncActivatedOnce()) {
6519 return OPINC_SUGGESTED_OR_EXCLUDED;
6520 }
6521 SetSuggestOpIncActivatedOnce();
6522
6523 if (GetApplicationRenderGroupMarked()) {
6524 return OPINC_INVALID;
6525 }
6526 auto status = IsOpIncValidNode(boundary, axis);
6527 if (SystemProperties::GetDebugEnabled()) {
6528 const auto& hostTag = GetHostTag();
6529 path = path + " --> " + hostTag;
6530 LOGD("FindSuggestOpIncNode : %{public}s, with depth %{public}d, boundary: %{public}f, self: %{public}f, "
6531 "status: %{public}d",
6532 path.c_str(), depth, boundary.Height(), GetGeometryNode()->GetFrameSize().Height(), status);
6533 }
6534 if (status == OPINC_NODE) {
6535 MarkSuggestOpIncGroup(true, true);
6536 return OPINC_SUGGESTED_OR_EXCLUDED;
6537 } else if (status == OPINC_SUGGESTED_OR_EXCLUDED) {
6538 return OPINC_SUGGESTED_OR_EXCLUDED;
6539 } else if (status == OPINC_PARENT_POSSIBLE) {
6540 std::list<RefPtr<FrameNode>> childrens;
6541 GenerateOneDepthVisibleFrame(childrens);
6542 for (auto& child : childrens) {
6543 if (child) {
6544 status = child->FindSuggestOpIncNode(path, boundary, depth + 1, axis);
6545 }
6546 if (status == OPINC_INVALID) {
6547 return OPINC_INVALID;
6548 }
6549 }
6550 return OPINC_PARENT_POSSIBLE;
6551 } else if (status == OPINC_INVALID) {
6552 return OPINC_INVALID;
6553 }
6554 return OPINC_SUGGESTED_OR_EXCLUDED;
6555 }
6556
MarkAndCheckNewOpIncNode(Axis axis)6557 void FrameNode::MarkAndCheckNewOpIncNode(Axis axis)
6558 {
6559 if (!IsActive() || GetSuggestOpIncActivatedOnce() || GetApplicationRenderGroupMarked()) {
6560 return;
6561 }
6562 auto parent = GetAncestorNodeOfFrame(true);
6563 CHECK_NULL_VOID(parent);
6564 if (parent->GetSuggestOpIncActivatedOnce()) {
6565 SetSuggestOpIncActivatedOnce();
6566 auto status = IsOpIncValidNode(parent->GetGeometryNode()->GetFrameSize(), axis);
6567 ACE_SCOPED_TRACE("MarkAndCheckNewOpIncNode id:%d, tag:%s, status: %d", nodeId_, tag_.c_str(), status);
6568 if (status == OPINC_NODE) {
6569 SetCanSuggestOpInc(true);
6570 MarkSuggestOpIncGroup(true, true);
6571 }
6572 }
6573 }
6574
GetValidLeafChildNumber(const RefPtr<FrameNode> & host,int32_t thresh)6575 int FrameNode::GetValidLeafChildNumber(const RefPtr<FrameNode>& host, int32_t thresh)
6576 {
6577 CHECK_NULL_RETURN(host, 0);
6578 auto total = 0;
6579 auto childSize = host->GetTotalChildCount();
6580 if (childSize < 1) {
6581 return 1;
6582 }
6583 for (auto i = 0; i < childSize; i++) {
6584 auto child = AceType::DynamicCast<FrameNode>(host->GetChildByIndex(i));
6585 if (!child) {
6586 continue;
6587 }
6588 total += GetValidLeafChildNumber(child, thresh);
6589 if (total >= thresh) {
6590 return total;
6591 }
6592 }
6593 return total;
6594 }
6595
TriggerShouldParallelInnerWith(const ResponseLinkResult & currentRecognizers,const ResponseLinkResult & responseLinkRecognizers)6596 void FrameNode::TriggerShouldParallelInnerWith(
6597 const ResponseLinkResult& currentRecognizers, const ResponseLinkResult& responseLinkRecognizers)
6598 {
6599 auto gestureHub = eventHub_ ? eventHub_->GetGestureEventHub() : nullptr;
6600 CHECK_NULL_VOID(gestureHub);
6601 auto shouldBuiltInRecognizerParallelWithFunc = gestureHub->GetParallelInnerGestureToFunc();
6602 CHECK_NULL_VOID(shouldBuiltInRecognizerParallelWithFunc);
6603 std::map<GestureTypeName, std::vector<RefPtr<NGGestureRecognizer>>> sortedResponseLinkRecognizers;
6604
6605 for (const auto& item : responseLinkRecognizers) {
6606 auto recognizer = AceType::DynamicCast<NGGestureRecognizer>(item);
6607 if (!recognizer) {
6608 continue;
6609 }
6610 auto type = recognizer->GetRecognizerType();
6611 sortedResponseLinkRecognizers[type].emplace_back(item);
6612 }
6613
6614 for (const auto& item : currentRecognizers) {
6615 if (!item->IsSystemGesture() || item->GetRecognizerType() != GestureTypeName::PAN_GESTURE) {
6616 continue;
6617 }
6618 auto multiRecognizer = AceType::DynamicCast<MultiFingersRecognizer>(item);
6619 if (!multiRecognizer || multiRecognizer->GetTouchPointsSize() > 1) {
6620 continue;
6621 }
6622 auto iter = sortedResponseLinkRecognizers.find(item->GetRecognizerType());
6623 if (iter == sortedResponseLinkRecognizers.end() || iter->second.empty()) {
6624 continue;
6625 }
6626 auto result = shouldBuiltInRecognizerParallelWithFunc(item, iter->second);
6627 if (result && item != result) {
6628 item->SetBridgeMode(true);
6629 result->AddBridgeObj(item);
6630 }
6631 }
6632 }
6633
GetInspectorValue()6634 void FrameNode::GetInspectorValue()
6635 {
6636 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(WEB_SUPPORTED) && defined(OHOS_PLATFORM)
6637 if (tag_ == V2::WEB_ETS_TAG) {
6638 UiSessionManager::GetInstance()->WebTaskNumsChange(1);
6639 auto pattern = GetPattern<NG::WebPattern>();
6640 CHECK_NULL_VOID(pattern);
6641 auto cb = [](std::shared_ptr<JsonValue> value, int32_t webId) {
6642 UiSessionManager::GetInstance()->AddValueForTree(webId, value->ToString());
6643 UiSessionManager::GetInstance()->WebTaskNumsChange(-1);
6644 };
6645 pattern->GetAllWebAccessibilityNodeInfos(cb, nodeId_);
6646 }
6647 #endif
6648 UINode::GetInspectorValue();
6649 }
6650
ClearSubtreeLayoutAlgorithm(bool includeSelf,bool clearEntireTree)6651 void FrameNode::ClearSubtreeLayoutAlgorithm(bool includeSelf, bool clearEntireTree)
6652 {
6653 // return when reaches a child that has no layoutAlgorithm and no need to clear the entire tree
6654 if (!layoutAlgorithm_ && !clearEntireTree) {
6655 return;
6656 }
6657 // include Self might be false for the first ClearSubtreeLayoutAlgorithm enter,
6658 // but children should always include themselves
6659 if (includeSelf) {
6660 layoutAlgorithm_.Reset();
6661 }
6662 for (const auto& child : GetChildren()) {
6663 child->ClearSubtreeLayoutAlgorithm(true, clearEntireTree);
6664 }
6665 }
6666
OnSyncGeometryFrameFinish(const RectF & paintRect)6667 void FrameNode::OnSyncGeometryFrameFinish(const RectF& paintRect)
6668 {
6669 if (syncedFramePaintRect_.has_value() && syncedFramePaintRect_.value() != paintRect) {
6670 AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_GEOMETRY_CHANGE);
6671 if (AnimationUtils::IsImplicitAnimationOpen()) {
6672 AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_START_ANIMATION);
6673 }
6674 }
6675 syncedFramePaintRect_ = paintRect;
6676 }
6677
AddFrameNodeChangeInfoFlag(FrameNodeChangeInfoFlag changeFlag)6678 void FrameNode::AddFrameNodeChangeInfoFlag(FrameNodeChangeInfoFlag changeFlag)
6679 {
6680 auto context = GetContext();
6681 CHECK_NULL_VOID(context);
6682 if (changeFlag == FRAME_NODE_CHANGE_GEOMETRY_CHANGE || changeFlag == FRAME_NODE_CHANGE_TRANSITION_START ||
6683 changeFlag == FRAME_NODE_CHANGE_TRANSFORM_CHANGE) {
6684 context->SetIsTransFlag(true);
6685 }
6686 if (changeInfoFlag_ == FRAME_NODE_CHANGE_INFO_NONE) {
6687 if (!context->AddChangedFrameNode(WeakClaim(this))) {
6688 return;
6689 }
6690 }
6691 changeInfoFlag_ = changeInfoFlag_ | changeFlag;
6692 }
6693
RegisterNodeChangeListener()6694 void FrameNode::RegisterNodeChangeListener()
6695 {
6696 ACE_LAYOUT_SCOPED_TRACE("RegisterNodeChangeListener:%s,%d", tag_.c_str(), nodeId_);
6697 auto context = GetContext();
6698 CHECK_NULL_VOID(context);
6699 context->AddFrameNodeChangeListener(WeakClaim(this));
6700 }
6701
UnregisterNodeChangeListener()6702 void FrameNode::UnregisterNodeChangeListener()
6703 {
6704 ACE_LAYOUT_SCOPED_TRACE("UnregisterNodeChangeListener:%s,%d", tag_.c_str(), nodeId_);
6705 auto context = GetContext();
6706 CHECK_NULL_VOID(context);
6707 context->RemoveFrameNodeChangeListener(nodeId_);
6708 }
6709
ProcessFrameNodeChangeFlag()6710 void FrameNode::ProcessFrameNodeChangeFlag()
6711 {
6712 ACE_LAYOUT_SCOPED_TRACE("ProcessFrameNodeChangeFlag:%s,%d", tag_.c_str(), nodeId_);
6713 auto changeFlag = FRAME_NODE_CHANGE_INFO_NONE;
6714 auto parent = Claim(this);
6715 while (parent) {
6716 changeFlag = changeFlag | parent->GetChangeInfoFlag();
6717 parent = parent->GetAncestorNodeOfFrame(true);
6718 if (changeFlag == FRAME_NODE_CHANGE_ALL) {
6719 break;
6720 }
6721 }
6722 if (changeFlag == FRAME_NODE_CHANGE_INFO_NONE) {
6723 return;
6724 }
6725 auto pattern = GetPattern();
6726 if (pattern) {
6727 ACE_LAYOUT_SCOPED_TRACE("OnFrameNodeChanged:%s,%d", tag_.c_str(), nodeId_);
6728 pattern->OnFrameNodeChanged(changeFlag);
6729 }
6730 }
6731
OnNodeTransformInfoUpdate(bool changed)6732 void FrameNode::OnNodeTransformInfoUpdate(bool changed)
6733 {
6734 if (!changed) {
6735 return;
6736 }
6737 AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_TRANSFORM_CHANGE);
6738 if (AnimationUtils::IsImplicitAnimationOpen()) {
6739 AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_START_ANIMATION);
6740 }
6741 }
6742
OnNodeTransitionInfoUpdate()6743 void FrameNode::OnNodeTransitionInfoUpdate()
6744 {
6745 AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_TRANSITION_START);
6746 }
6747
NotifyWebPattern(bool isRegister)6748 void FrameNode::NotifyWebPattern(bool isRegister)
6749 {
6750 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(WEB_SUPPORTED) && defined(OHOS_PLATFORM)
6751 if (tag_ == V2::WEB_ETS_TAG) {
6752 auto pattern = GetPattern<NG::WebPattern>();
6753 CHECK_NULL_VOID(pattern);
6754 auto report = pattern->GetAccessibilityEventReport();
6755 CHECK_NULL_VOID(report);
6756 if (isRegister) {
6757 report->RegisterAllReportEventCallBack();
6758 } else {
6759 report->UnRegisterCallback();
6760 }
6761 }
6762 #endif
6763 UINode::NotifyWebPattern(isRegister);
6764 }
6765
GetWindowPatternType() const6766 uint32_t FrameNode::GetWindowPatternType() const
6767 {
6768 CHECK_NULL_RETURN(pattern_, 0);
6769 return pattern_->GetWindowPatternType();
6770 }
6771
NotifyChange(int32_t index,int32_t count,int64_t id,NotificationType notificationType)6772 void FrameNode::NotifyChange(int32_t index, int32_t count, int64_t id, NotificationType notificationType)
6773 {
6774 int32_t updateFrom = CalcAbsPosition(index, id);
6775 auto pattern = GetPattern();
6776 switch (notificationType) {
6777 case NotificationType::START_CHANGE_POSITION:
6778 ChildrenUpdatedFrom(updateFrom);
6779 break;
6780 case NotificationType::END_CHANGE_POSITION:
6781 pattern->NotifyDataChange(updateFrom, count);
6782 break;
6783 case NotificationType::START_AND_END_CHANGE_POSITION:
6784 ChildrenUpdatedFrom(updateFrom);
6785 pattern->NotifyDataChange(updateFrom, count);
6786 break;
6787 default:
6788 break;
6789 }
6790 }
6791
6792 // for Grid refresh GridItems
ChildrenUpdatedFrom(int32_t index)6793 void FrameNode::ChildrenUpdatedFrom(int32_t index)
6794 {
6795 childrenUpdatedFrom_ = childrenUpdatedFrom_ >= 0 ? std::min(index, childrenUpdatedFrom_) : index;
6796 }
6797
OnThemeScopeUpdate(int32_t themeScopeId)6798 void FrameNode::OnThemeScopeUpdate(int32_t themeScopeId)
6799 {
6800 TAG_LOGD(AceLogTag::ACE_DEFAULT_DOMAIN, "WithTheme Node(%{public}s/%{public}d) OnThemeScopeUpdate id:%{public}d",
6801 tag_.c_str(), nodeId_, themeScopeId);
6802 if (pattern_->OnThemeScopeUpdate(themeScopeId)) {
6803 MarkDirtyNode(PROPERTY_UPDATE_RENDER);
6804 }
6805 }
6806
DumpOnSizeChangeInfo(std::unique_ptr<JsonValue> & json)6807 void FrameNode::DumpOnSizeChangeInfo(std::unique_ptr<JsonValue>& json)
6808 {
6809 std::unique_ptr<JsonValue> children = JsonUtil::CreateArray(true);
6810 for (auto it = onSizeChangeDumpInfos.rbegin(); it != onSizeChangeDumpInfos.rend(); ++it) {
6811 std::unique_ptr<JsonValue> child = JsonUtil::Create(true);
6812 child->Put("onSizeChange Time", it->onSizeChangeTimeStamp);
6813 child->Put("lastFrameRect", it->lastFrameRect.ToString().c_str());
6814 child->Put("currFrameRect", it->currFrameRect.ToString().c_str());
6815 children->Put(child);
6816 }
6817 children->Put("SizeChangeInfo", children);
6818 }
6819
DumpOverlayInfo(std::unique_ptr<JsonValue> & json)6820 void FrameNode::DumpOverlayInfo(std::unique_ptr<JsonValue>& json)
6821 {
6822 if (!layoutProperty_->IsOverlayNode()) {
6823 return;
6824 }
6825 json->Put("IsOverlayNode", "true");
6826 Dimension offsetX, offsetY;
6827 layoutProperty_->GetOverlayOffset(offsetX, offsetY);
6828 std::unique_ptr<JsonValue> children = JsonUtil::Create(true);
6829 children->Put("x", offsetX.ToString().c_str());
6830 children->Put("y", offsetY.ToString().c_str());
6831 json->Put("OverlayOffset", children);
6832 }
6833
DumpDragInfo(std::unique_ptr<JsonValue> & json)6834 void FrameNode::DumpDragInfo(std::unique_ptr<JsonValue>& json)
6835 {
6836 json->Put("Draggable", draggable_ ? "true" : "false");
6837 json->Put("UserSet", userSet_ ? "true" : "false");
6838 json->Put("CustomerSet", customerSet_ ? "true" : "false");
6839 std::unique_ptr<JsonValue> dragPreview = JsonUtil::Create(true);
6840 dragPreview->Put("Has customNode", dragPreviewInfo_.customNode ? "YES" : "NO");
6841 dragPreview->Put("Has pixelMap", dragPreviewInfo_.pixelMap ? "YES" : "NO");
6842 dragPreview->Put("extraInfo", dragPreviewInfo_.extraInfo.c_str());
6843 dragPreview->Put("inspectorId", dragPreviewInfo_.inspectorId.c_str());
6844 json->Put("DragPreview", dragPreview);
6845
6846 auto eventHub = GetEventHub<EventHub>();
6847 std::unique_ptr<JsonValue> event = JsonUtil::Create(true);
6848 event->Put("OnDragStart", eventHub && eventHub->HasOnDragStart() ? "YES" : "NO");
6849 event->Put("OnDragEnter", eventHub && eventHub->HasOnDragEnter() ? "YES" : "NO");
6850 event->Put("OnDragLeave", eventHub && eventHub->HasOnDragLeave() ? "YES" : "NO");
6851 event->Put("OnDragMove", eventHub && eventHub->HasOnDragMove() ? "YES" : "NO");
6852 event->Put("OnDrop", eventHub && eventHub->HasOnDrop() ? "YES" : "NO");
6853 event->Put("OnDragEnd", eventHub && eventHub->HasOnDragEnd() ? "YES" : "NO");
6854 event->Put("DefaultOnDragStart", eventHub && eventHub->HasDefaultOnDragStart() ? "YES" : "NO");
6855 event->Put("CustomerOnDragEnter", eventHub && eventHub->HasCustomerOnDragEnter() ? "YES" : "NO");
6856 event->Put("CustomerOnDragLeave", eventHub && eventHub->HasCustomerOnDragLeave() ? "YES" : "NO");
6857 event->Put("CustomerOnDragMove", eventHub && eventHub->HasCustomerOnDragMove() ? "YES" : "NO");
6858 event->Put("CustomerOnDrop", eventHub && eventHub->HasCustomerOnDrop() ? "YES" : "NO");
6859 event->Put("CustomerOnDragEnd", eventHub && eventHub->HasCustomerOnDragEnd() ? "YES" : "NO");
6860 json->Put("Event", event);
6861 }
6862
DumpAlignRulesInfo(std::unique_ptr<JsonValue> & json)6863 void FrameNode::DumpAlignRulesInfo(std::unique_ptr<JsonValue>& json)
6864 {
6865 auto& flexItemProperties = layoutProperty_->GetFlexItemProperty();
6866 CHECK_NULL_VOID(flexItemProperties);
6867 auto rulesToString = flexItemProperties->AlignRulesToString();
6868 CHECK_NULL_VOID(!rulesToString.empty());
6869 json->Put("AlignRules", rulesToString.c_str());
6870 }
6871
DumpSafeAreaInfo(std::unique_ptr<JsonValue> & json)6872 void FrameNode::DumpSafeAreaInfo(std::unique_ptr<JsonValue>& json)
6873 {
6874 if (layoutProperty_->GetSafeAreaExpandOpts()) {
6875 json->Put("SafeAreaExpandOpts", layoutProperty_->GetSafeAreaExpandOpts()->ToString().c_str());
6876 }
6877 if (layoutProperty_->GetSafeAreaInsets()) {
6878 json->Put("SafeAreaInsets", layoutProperty_->GetSafeAreaInsets()->ToString().c_str());
6879 }
6880 if (SelfOrParentExpansive()) {
6881 json->Put("selfAdjust", geometryNode_->GetSelfAdjust().ToString().c_str());
6882 json->Put("parentAdjust", geometryNode_->GetParentAdjust().ToString().c_str());
6883 }
6884 CHECK_NULL_VOID(tag_ == V2::PAGE_ETS_TAG);
6885 auto pipeline = GetContext();
6886 CHECK_NULL_VOID(pipeline);
6887 auto manager = pipeline->GetSafeAreaManager();
6888 CHECK_NULL_VOID(manager);
6889 json->Put("ignoreSafeArea", std::to_string(manager->IsIgnoreSafeArea()).c_str());
6890 json->Put("isNeedAvoidWindow", std::to_string(manager->IsNeedAvoidWindow()).c_str());
6891 json->Put("isFullScreen", std::to_string(manager->IsFullScreen()).c_str());
6892 json->Put("isKeyboardAvoidMode", std::to_string(static_cast<int32_t>(manager->GetKeyBoardAvoidMode())).c_str());
6893 json->Put("isUseCutout", std::to_string(manager->GetUseCutout()).c_str());
6894 }
6895
DumpExtensionHandlerInfo(std::unique_ptr<JsonValue> & json)6896 void FrameNode::DumpExtensionHandlerInfo(std::unique_ptr<JsonValue>& json)
6897 {
6898 if (!extensionHandler_) {
6899 return;
6900 }
6901 std::unique_ptr<JsonValue> extensionHandler = JsonUtil::Create(true);
6902 extensionHandler->Put("HasCustomerMeasure", extensionHandler_->HasCustomerMeasure() ? "true" : "false");
6903 extensionHandler->Put("HasCustomerLayout", extensionHandler_->HasCustomerLayout() ? "true" : "false");
6904 json->Put("ExtensionHandler", extensionHandler);
6905 }
6906
BuildLayoutInfo(std::unique_ptr<JsonValue> & json)6907 void FrameNode::BuildLayoutInfo(std::unique_ptr<JsonValue>& json)
6908 {
6909 if (geometryNode_->GetParentLayoutConstraint().has_value()) {
6910 json->Put("ParentLayoutConstraint", geometryNode_->GetParentLayoutConstraint().value().ToString().c_str());
6911 }
6912 if (!(NearZero(GetOffsetRelativeToWindow().GetY()) && NearZero(GetOffsetRelativeToWindow().GetX()))) {
6913 json->Put("top", GetOffsetRelativeToWindow().GetY());
6914 json->Put("left", GetOffsetRelativeToWindow().GetX());
6915 }
6916 if (static_cast<int32_t>(IsActive()) != 1) {
6917 json->Put("Active", static_cast<int32_t>(IsActive()));
6918 }
6919 if (static_cast<int32_t>(layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)) != 0) {
6920 json->Put("Visible", static_cast<int32_t>(layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)));
6921 }
6922 if (layoutProperty_->GetPaddingProperty()) {
6923 json->Put("Padding", layoutProperty_->GetPaddingProperty()->ToString().c_str());
6924 }
6925 if (layoutProperty_->GetSafeAreaPaddingProperty()) {
6926 json->Put("SafeArea Padding", layoutProperty_->GetSafeAreaPaddingProperty()->ToString().c_str());
6927 }
6928 if (layoutProperty_->GetBorderWidthProperty()) {
6929 json->Put("Border", layoutProperty_->GetBorderWidthProperty()->ToString().c_str());
6930 }
6931 if (layoutProperty_->GetMarginProperty()) {
6932 json->Put("Margin", layoutProperty_->GetMarginProperty()->ToString().c_str());
6933 }
6934 if (layoutProperty_->GetLayoutRect()) {
6935 json->Put("LayoutRect", layoutProperty_->GetLayoutRect().value().ToString().c_str());
6936 }
6937 }
6938
DumpCommonInfo(std::unique_ptr<JsonValue> & json)6939 void FrameNode::DumpCommonInfo(std::unique_ptr<JsonValue>& json)
6940 {
6941 json->Put("FrameRect", geometryNode_->GetFrameRect().ToString().c_str());
6942 json->Put("PaintRect without transform", renderContext_->GetPaintRectWithoutTransform().ToString().c_str());
6943 if (renderContext_->GetBackgroundColor()->ColorToString().compare("#00000000") != 0) {
6944 json->Put("BackgroundColor", renderContext_->GetBackgroundColor()->ColorToString().c_str());
6945 }
6946 BuildLayoutInfo(json);
6947 DumpExtensionHandlerInfo(json);
6948 DumpSafeAreaInfo(json);
6949 if (layoutProperty_->GetCalcLayoutConstraint()) {
6950 json->Put("User defined constraint", layoutProperty_->GetCalcLayoutConstraint()->ToString().c_str());
6951 }
6952 if (!propInspectorId_->empty()) {
6953 json->Put("compid", propInspectorId_.value_or("").c_str());
6954 }
6955 if (layoutProperty_->GetPaddingProperty() || layoutProperty_->GetBorderWidthProperty() ||
6956 layoutProperty_->GetMarginProperty() || layoutProperty_->GetCalcLayoutConstraint()) {
6957 json->Put("ContentConstraint", layoutProperty_->GetContentLayoutConstraint().has_value()
6958 ? layoutProperty_->GetContentLayoutConstraint().value().ToString().c_str()
6959 : "NA");
6960 }
6961 DumpAlignRulesInfo(json);
6962 DumpDragInfo(json);
6963 DumpOverlayInfo(json);
6964 if (frameProxy_->Dump().compare("totalCount is 0") != 0) {
6965 json->Put("FrameProxy", frameProxy_->Dump().c_str());
6966 }
6967 }
6968
DumpInfo(std::unique_ptr<JsonValue> & json)6969 void FrameNode::DumpInfo(std::unique_ptr<JsonValue>& json)
6970 {
6971 DumpCommonInfo(json);
6972 DumpOnSizeChangeInfo(json);
6973 if (pattern_) {
6974 pattern_->DumpInfo(json);
6975 }
6976 if (renderContext_) {
6977 renderContext_->DumpInfo(json);
6978 }
6979 }
6980
DumpAdvanceInfo(std::unique_ptr<JsonValue> & json)6981 void FrameNode::DumpAdvanceInfo(std::unique_ptr<JsonValue>& json)
6982 {
6983 DumpCommonInfo(json);
6984 DumpOnSizeChangeInfo(json);
6985 if (pattern_) {
6986 pattern_->DumpInfo(json);
6987 pattern_->DumpAdvanceInfo(json);
6988 }
6989 if (renderContext_) {
6990 renderContext_->DumpInfo(json);
6991 renderContext_->DumpAdvanceInfo(json);
6992 }
6993 }
6994
ResetPredictNodes()6995 void FrameNode::ResetPredictNodes()
6996 {
6997 auto predictLayoutNode = std::move(predictLayoutNode_);
6998 for (auto& node : predictLayoutNode) {
6999 auto frameNode = node.Upgrade();
7000 if (frameNode && frameNode->isLayoutDirtyMarked_) {
7001 frameNode->isLayoutDirtyMarked_ = false;
7002 }
7003 }
7004 }
7005
SetJSCustomProperty(std::function<bool ()> func,std::function<std::string (const std::string &)> getFunc,std::function<std::string ()> && getCustomPropertyMapFunc)7006 void FrameNode::SetJSCustomProperty(std::function<bool()> func, std::function<std::string(const std::string&)> getFunc,
7007 std::function<std::string()>&& getCustomPropertyMapFunc)
7008 {
7009 func();
7010 if (IsCNode()) {
7011 return;
7012 }
7013 if (!getCustomProperty_) {
7014 getCustomProperty_ = getFunc;
7015 }
7016 if (getCustomPropertyMapFunc && (!getCustomPropertyMapFunc_)) {
7017 getCustomPropertyMapFunc_ = std::move(getCustomPropertyMapFunc);
7018 }
7019 }
7020
GetJSCustomProperty(const std::string & key,std::string & value)7021 bool FrameNode::GetJSCustomProperty(const std::string& key, std::string& value)
7022 {
7023 auto iter = customPropertyMap_.find(key);
7024 if (iter != customPropertyMap_.end() && !iter->second.empty()) {
7025 if (iter->second[1] == "1") {
7026 value = iter->second[0];
7027 return true;
7028 } else if (getCustomProperty_) {
7029 value = getCustomProperty_(key);
7030 iter->second[0] = value;
7031 iter->second[1] = "1";
7032 return true;
7033 }
7034 }
7035 return false;
7036 }
7037
GetCapiCustomProperty(const std::string & key,std::string & value)7038 bool FrameNode::GetCapiCustomProperty(const std::string& key, std::string& value)
7039 {
7040 auto iter = customPropertyMap_.find(key);
7041 if (iter != customPropertyMap_.end()) {
7042 value = iter->second[0];
7043 return true;
7044 }
7045 return false;
7046 }
7047
AddCustomProperty(const std::string & key,const std::string & value)7048 void FrameNode::AddCustomProperty(const std::string& key, const std::string& value)
7049 {
7050 customPropertyMap_[key] = {value, "1"};
7051 }
7052
RemoveCustomProperty(const std::string & key)7053 void FrameNode::RemoveCustomProperty(const std::string& key)
7054 {
7055 auto iter = customPropertyMap_.find(key);
7056 if (iter != customPropertyMap_.end()) {
7057 customPropertyMap_.erase(iter);
7058 }
7059 }
7060
SetCustomPropertyMapFlagByKey(const std::string & key)7061 void FrameNode::SetCustomPropertyMapFlagByKey(const std::string& key)
7062 {
7063 auto& valueVector = customPropertyMap_[key];
7064 if (valueVector.empty()) {
7065 valueVector = {"", "0"};
7066 } else {
7067 valueVector[1] = "0";
7068 }
7069 }
7070
AddExtraCustomProperty(const std::string & key,void * extraData)7071 void FrameNode::AddExtraCustomProperty(const std::string& key, void* extraData)
7072 {
7073 extraCustomPropertyMap_[key] = extraData;
7074 }
7075
GetExtraCustomProperty(const std::string & key) const7076 void* FrameNode::GetExtraCustomProperty(const std::string& key) const
7077 {
7078 auto iter = extraCustomPropertyMap_.find(key);
7079 if (iter != extraCustomPropertyMap_.end()) {
7080 return iter->second;
7081 }
7082 return nullptr;
7083 }
7084
RemoveExtraCustomProperty(const std::string & key)7085 void FrameNode::RemoveExtraCustomProperty(const std::string& key)
7086 {
7087 auto iter = extraCustomPropertyMap_.find(key);
7088 if (iter != extraCustomPropertyMap_.end()) {
7089 extraCustomPropertyMap_.erase(iter);
7090 }
7091 }
7092
ExtraCustomPropertyToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const7093 void FrameNode::ExtraCustomPropertyToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
7094 {
7095 auto mapIter = extraCustomPropertyMap_.find("ToJsonValue");
7096 if (mapIter == extraCustomPropertyMap_.end()) {
7097 return;
7098 }
7099
7100 auto callback = reinterpret_cast<std::map<std::string, std::string>(*)(std::unordered_map<std::string, void*>)>(
7101 mapIter->second);
7102 CHECK_NULL_VOID(callback);
7103 auto jsonValue = callback(extraCustomPropertyMap_);
7104 for (auto iter = jsonValue.begin(); iter != jsonValue.end(); iter++) {
7105 json->PutExtAttr(iter->first.c_str(), iter->second.c_str(), filter);
7106 }
7107 }
7108
IsDebugInspectorId()7109 bool FrameNode::IsDebugInspectorId()
7110 {
7111 if (!SystemProperties::GetDebugEnabled()) {
7112 return false;
7113 }
7114 auto debugInspectorId = SystemProperties::GetDebugInspectorId();
7115 return debugInspectorId == GetInspectorId().value_or("");
7116 }
7117
GetCurrentPageRootNode()7118 RefPtr<UINode> FrameNode::GetCurrentPageRootNode()
7119 {
7120 auto pageNode = GetPageNode();
7121 CHECK_NULL_RETURN(pageNode, nullptr);
7122 auto jsView = pageNode->GetChildAtIndex(0);
7123 CHECK_NULL_RETURN(jsView, nullptr);
7124 if (jsView->GetTag() == V2::JS_VIEW_ETS_TAG) {
7125 auto rootNode = jsView->GetChildAtIndex(0);
7126 CHECK_NULL_RETURN(rootNode, nullptr);
7127 return rootNode;
7128 }
7129 return jsView;
7130 }
7131
GetActiveChildren()7132 std::list<RefPtr<FrameNode>> FrameNode::GetActiveChildren()
7133 {
7134 std::list<RefPtr<FrameNode>> list;
7135 for (int32_t i = 0; i < TotalChildCount(); i++) {
7136 auto child = GetFrameNodeChildByIndex(i, false, false);
7137 if (child->IsActive()) {
7138 list.emplace_back(Referenced::Claim(child));
7139 }
7140 }
7141 return list;
7142 }
7143
CleanVisibleAreaUserCallback(bool isApproximate)7144 void FrameNode::CleanVisibleAreaUserCallback(bool isApproximate)
7145 {
7146 CHECK_NULL_VOID(eventHub_);
7147 auto hasInnerCallback = eventHub_->HasVisibleAreaCallback(false);
7148 auto hasUserCallback = eventHub_->HasVisibleAreaCallback(true);
7149 auto& throttledVisibleAreaCallback = eventHub_->GetThrottledVisibleAreaCallback();
7150 auto pipeline = GetContext();
7151 if (isApproximate) {
7152 eventHub_->CleanVisibleAreaCallback(true, isApproximate);
7153 if (!hasInnerCallback && !hasUserCallback && pipeline) {
7154 throttledCallbackOnTheWay_ = false;
7155 pipeline->RemoveVisibleAreaChangeNode(nodeId_);
7156 }
7157 } else {
7158 eventHub_->CleanVisibleAreaCallback(true, false);
7159 if (!hasInnerCallback && !throttledVisibleAreaCallback.callback && pipeline) {
7160 pipeline->RemoveVisibleAreaChangeNode(nodeId_);
7161 }
7162 }
7163 }
7164
SetKitNode(const RefPtr<Kit::FrameNode> & node)7165 void FrameNode::SetKitNode(const RefPtr<Kit::FrameNode>& node)
7166 {
7167 kitNode_ = node;
7168 }
7169
GetCustomPropertyByKey(const std::string & key,std::string & value)7170 bool FrameNode::GetCustomPropertyByKey(const std::string& key, std::string& value)
7171 {
7172 auto iter = customPropertyMap_.find(key);
7173 if (iter != customPropertyMap_.end() && !iter->second.empty()) {
7174 value = iter->second[0];
7175 return true;
7176 }
7177 return false;
7178 }
7179
AddNodeDestroyCallback(const std::string & callbackKey,std::function<void ()> && callback)7180 void FrameNode::AddNodeDestroyCallback(const std::string& callbackKey, std::function<void()>&& callback)
7181 {
7182 if (!callback) {
7183 return;
7184 }
7185 destroyCallbacks_[callbackKey] = std::move(callback);
7186 }
7187
RemoveNodeDestroyCallback(const std::string & callbackKey)7188 void FrameNode::RemoveNodeDestroyCallback(const std::string& callbackKey)
7189 {
7190 auto iter = destroyCallbacks_.find(callbackKey);
7191 if (iter != destroyCallbacks_.end()) {
7192 destroyCallbacks_.erase(iter);
7193 }
7194 }
7195
FireOnExtraNodeDestroyCallback()7196 void FrameNode::FireOnExtraNodeDestroyCallback()
7197 {
7198 for (const auto& callback : destroyCallbacks_) {
7199 callback.second();
7200 }
7201 }
7202
SetFrameNodeDestructorCallback(const std::function<void (int32_t)> && callback)7203 void FrameNode::SetFrameNodeDestructorCallback(const std::function<void(int32_t)>&& callback)
7204 {
7205 frameNodeDestructorCallback_ = callback;
7206 }
7207
FireFrameNodeDestructorCallback()7208 void FrameNode::FireFrameNodeDestructorCallback()
7209 {
7210 if (frameNodeDestructorCallback_) {
7211 frameNodeDestructorCallback_(nodeId_);
7212 }
7213 }
7214
GetPatternTypeName() const7215 const char* FrameNode::GetPatternTypeName() const
7216 {
7217 return TypeInfoHelper::TypeName(RawPtr(pattern_));
7218 }
7219
GetLayoutPropertyTypeName() const7220 const char* FrameNode::GetLayoutPropertyTypeName() const
7221 {
7222 return TypeInfoHelper::TypeName(RawPtr(layoutProperty_));
7223 }
7224
GetPaintPropertyTypeName() const7225 const char* FrameNode::GetPaintPropertyTypeName() const
7226 {
7227 return TypeInfoHelper::TypeName(RawPtr(paintProperty_));
7228 }
7229
GetKitNode() const7230 const RefPtr<Kit::FrameNode>& FrameNode::GetKitNode() const
7231 {
7232 return kitNode_;
7233 }
7234
IsDrawFocusOnTop() const7235 bool FrameNode::IsDrawFocusOnTop() const
7236 {
7237 auto accessibilityProperty = GetAccessibilityProperty<NG::AccessibilityProperty>();
7238 CHECK_NULL_RETURN(accessibilityProperty, false);
7239 return static_cast<FocusDrawLevel>(accessibilityProperty->GetFocusDrawLevel()) == FocusDrawLevel::TOP;
7240 }
7241
OnRecvCommand(const std::string & command)7242 int32_t FrameNode::OnRecvCommand(const std::string& command)
7243 {
7244 auto pattern = GetPattern();
7245 CHECK_NULL_RETURN(pattern, RET_FAILED);
7246 return pattern->OnRecvCommand(command);
7247 }
7248
HandleAreaChangeDestruct()7249 void FrameNode::HandleAreaChangeDestruct()
7250 {
7251 if (eventHub_) {
7252 eventHub_->ClearOnAreaChangedInnerCallbacks();
7253 if (eventHub_->HasVisibleAreaCallback(true) || eventHub_->HasVisibleAreaCallback(false) ||
7254 eventHub_->HasThrottledVisibleAreaCallback()) {
7255 SetVisibleAreaChangeTriggerReason(VisibleAreaChangeTriggerReason::FRAMENODE_DESTROY);
7256 TriggerVisibleAreaChangeCallback(0, true);
7257 CleanVisibleAreaUserCallback(true);
7258 CleanVisibleAreaUserCallback();
7259 CleanVisibleAreaInnerCallback();
7260 }
7261 }
7262 }
7263
AddToOcclusionMap(bool enable)7264 void FrameNode::AddToOcclusionMap(bool enable)
7265 {
7266 auto context = GetContextWithCheck();
7267 CHECK_NULL_VOID(context);
7268 context->AddToOcclusionMap(nodeId_, enable);
7269 }
7270
CleanupPipelineResources()7271 void FrameNode::CleanupPipelineResources()
7272 {
7273 auto pipeline = PipelineContext::GetCurrentContext();
7274 if (pipeline) {
7275 pipeline->RemoveOnAreaChangeNode(nodeId_);
7276 pipeline->RemoveVisibleAreaChangeNode(nodeId_);
7277 pipeline->ChangeMouseStyle(nodeId_, MouseFormat::DEFAULT);
7278 pipeline->FreeMouseStyleHoldNode(nodeId_);
7279 pipeline->RemoveStoredNode(GetRestoreId());
7280 auto dragManager = pipeline->GetDragDropManager();
7281 if (dragManager) {
7282 dragManager->RemoveDragFrameNode(nodeId_);
7283 dragManager->UnRegisterDragStatusListener(nodeId_);
7284 }
7285 auto frameRateManager = pipeline->GetFrameRateManager();
7286 if (frameRateManager) {
7287 frameRateManager->RemoveNodeRate(nodeId_);
7288 }
7289 pipeline->RemoveChangedFrameNode(nodeId_);
7290 pipeline->RemoveFrameNodeChangeListener(nodeId_);
7291 pipeline->GetNodeRenderStatusMonitor()->NotifyFrameNodeRelease(this);
7292 }
7293 }
7294
SetAICallerHelper(const std::shared_ptr<AICallerHelper> & aiCallerHelper)7295 void FrameNode::SetAICallerHelper(const std::shared_ptr<AICallerHelper>& aiCallerHelper)
7296 {
7297 aiCallerHelper_ = aiCallerHelper;
7298 }
7299
CallAIFunction(const std::string & functionName,const std::string & params)7300 uint32_t FrameNode::CallAIFunction(const std::string& functionName, const std::string& params)
7301 {
7302 static constexpr uint32_t AI_CALL_SUCCESS = 0;
7303 static constexpr uint32_t AI_CALLER_INVALID = 1;
7304 static constexpr uint32_t AI_CALL_FUNCNAME_INVALID = 2;
7305 if (aiCallerHelper_) {
7306 return aiCallerHelper_->onAIFunctionCaller(functionName, params) ?
7307 AI_CALL_SUCCESS :
7308 AI_CALL_FUNCNAME_INVALID;
7309 }
7310 return AI_CALLER_INVALID;
7311 }
7312
UpdateBackground()7313 void FrameNode::UpdateBackground()
7314 {
7315 // if node has background, do update.
7316 if (renderContext_->HasBuilderBackgroundFlag()) {
7317 bool isBuilderBackground = renderContext_->GetBuilderBackgroundFlag().value();
7318 if (isBuilderBackground && builderFunc_) {
7319 auto builderNode = builderFunc_();
7320 auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG,
7321 ElementRegister::GetInstance()->MakeUniqueId(), AceType::MakeRefPtr<LinearLayoutPattern>(true));
7322 if (builderNode) {
7323 builderNode->MountToParent(columnNode);
7324 }
7325 SetBackgroundLayoutConstraint(columnNode);
7326 renderContext_->CreateBackgroundPixelMap(columnNode);
7327 builderFunc_ = nullptr;
7328 backgroundNode_ = columnNode;
7329 } else if (!isBuilderBackground) {
7330 renderContext_->UpdateCustomBackground();
7331 }
7332 }
7333 }
7334
UpdateIgnoreCount(int inc)7335 void FrameNode::UpdateIgnoreCount(int inc)
7336 {
7337 subtreeIgnoreCount_ += inc;
7338 if (!isActive_) {
7339 return;
7340 }
7341 auto parent = GetAncestorNodeOfFrame(false);
7342 if (parent) {
7343 parent->UpdateIgnoreCount(inc);
7344 }
7345 }
7346
MountToParent(const RefPtr<UINode> & parent,int32_t slot,bool silently,bool addDefaultTransition,bool addModalUiextension)7347 void FrameNode::MountToParent(const RefPtr<UINode>& parent,
7348 int32_t slot, bool silently, bool addDefaultTransition, bool addModalUiextension)
7349 {
7350 CHECK_NULL_VOID(parent);
7351 parent->AddChild(AceType::Claim(this), slot, silently, addDefaultTransition, addModalUiextension);
7352 if (SubtreeWithIgnoreChild()) {
7353 auto parentFrame = GetAncestorNodeOfFrame(false);
7354 if (parentFrame && IsActive()) {
7355 if (SystemProperties::GetMeasureDebugTraceEnabled()) {
7356 ACE_MEASURE_SCOPED_TRACE("UpdateIgnoreCount:MountToParent[%s][self:%d] updateCount=%d", tag_.c_str(),
7357 nodeId_, subtreeIgnoreCount_);
7358 }
7359 parentFrame->UpdateIgnoreCount(subtreeIgnoreCount_);
7360 }
7361 }
7362 if (parent->IsInDestroying()) {
7363 parent->SetChildrenInDestroying();
7364 }
7365 if (parent->GetPageId() != 0) {
7366 SetHostPageId(parent->GetPageId());
7367 }
7368 AfterMountToParent();
7369 }
7370 } // namespace OHOS::Ace::NG
7371