1 /*
2 * Copyright (c) 2022-2024 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 <cstdint>
19
20 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
21 #include "core/common/layout_inspector.h"
22 #include "interfaces/inner_api/ui_session/ui_session_manager.h"
23 #include "frameworks/core/components_ng/pattern/web/web_pattern.h"
24 #endif
25 #include "base/geometry/ng/rect_t.h"
26 #include "core/pipeline/base/element_register.h"
27 #include "base/geometry/dimension.h"
28 #include "base/geometry/ng/offset_t.h"
29 #include "base/geometry/ng/point_t.h"
30 #include "base/log/ace_performance_monitor.h"
31 #include "base/log/ace_trace.h"
32 #include "base/log/dump_log.h"
33 #include "base/log/log_wrapper.h"
34 #include "base/memory/ace_type.h"
35 #include "base/memory/referenced.h"
36 #include "base/thread/cancelable_callback.h"
37 #include "base/thread/task_executor.h"
38 #include "base/utils/system_properties.h"
39 #include "base/utils/time_util.h"
40 #include "base/utils/utils.h"
41 #include "core/common/ace_application_info.h"
42 #include "core/common/container.h"
43 #include "core/common/recorder/event_recorder.h"
44 #include "core/common/recorder/node_data_cache.h"
45 #include "core/common/stylus/stylus_detector_mgr.h"
46 #include "core/components/common/layout/constants.h"
47 #include "core/components/common/layout/grid_system_manager.h"
48 #include "core/components_ng/base/extension_handler.h"
49 #include "core/components_ng/base/frame_scene_status.h"
50 #include "core/components_ng/base/inspector.h"
51 #include "core/components_ng/base/inspector_filter.h"
52 #include "core/components_ng/base/ui_node.h"
53 #include "core/components_ng/event/drag_event.h"
54 #include "core/components_ng/event/gesture_event_hub.h"
55 #include "core/components_ng/event/target_component.h"
56 #include "core/components_ng/gestures/recognizers/multi_fingers_recognizer.h"
57 #include "core/components_ng/layout/layout_algorithm.h"
58 #include "core/components_ng/layout/layout_wrapper.h"
59 #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h"
60 #include "core/components_ng/pattern/pattern.h"
61 #include "core/components_ng/pattern/stage/page_pattern.h"
62 #include "core/components_ng/property/measure_property.h"
63 #include "core/components_ng/property/measure_utils.h"
64 #include "core/components_ng/property/property.h"
65 #include "core/components_ng/render/paint_wrapper.h"
66 #include "core/components_ng/syntax/lazy_for_each_node.h"
67 #include "core/components_ng/syntax/repeat_virtual_scroll_node.h"
68 #include "core/components_v2/inspector/inspector_constants.h"
69 #include "core/event/touch_event.h"
70 #include "core/gestures/gesture_info.h"
71 #include "core/pipeline_ng/pipeline_context.h"
72 #include "core/pipeline_ng/ui_task_scheduler.h"
73
74 namespace {
75 constexpr double VISIBLE_RATIO_MIN = 0.0;
76 constexpr double VISIBLE_RATIO_MAX = 1.0;
77 constexpr int32_t SUBSTR_LENGTH = 3;
78 const char DIMENSION_UNIT_VP[] = "vp";
79 constexpr int32_t SIZE_CHANGE_DUMP_SIZE = 5;
80 constexpr double MIN_WIDTH = 5.0;
81 constexpr double MIN_HEIGHT = 5.0;
82 constexpr double MIN_OPACITY = 0.1;
83 constexpr uint64_t MATRIX_CACHE_TIME_THRESHOLD = 15000000000;
84 /* suggestOpIncByte_s status mask, to indicate different aspects of node status
85 * related with suggestion OPINC improvements.
86 * for internal use; subject to change.
87 */
88 // suggest opinc marked.
89 constexpr uint8_t SUGGEST_OPINC_MARKED_MASK = 1;
90 // Whether the node can be suggest opinc marked.
91 constexpr uint8_t CAN_SUGGEST_OPINC_MASK = 1 << 1;
92 // The node already activated for suggest opinc.
93 constexpr uint8_t SUGGEST_OPINC_ACTIVATED_ONCE = 1 << 2;
94 // The node already checked for suggest opinc.
95 constexpr uint8_t SUGGEST_OPINC_CHCKED_ONCE = 1 << 3;
96 // The node has checked through for lazy new nodes.
97 constexpr uint8_t SUGGEST_OPINC_CHECKED_THROUGH = 1 << 4;
98 // Node has rendergroup marked.
99 constexpr uint8_t APP_RENDER_GROUP_MARKED_MASK = 1 << 7;
100 // OPINC must more then 2 leaf;
101 constexpr int32_t THRESH_CHILD_NO = 2;
102 // OPINC max ratio for scroll scope(height);
103 constexpr float HIGHT_RATIO_LIMIT = 0.8;
104 // Min area for OPINC
105 constexpr int32_t MIN_OPINC_AREA = 10000;
106 constexpr char UPDATE_FLAG_KEY[] = "updateFlag";
107 constexpr int32_t DEFAULT_PRECISION = 2;
108 } // namespace
109 namespace OHOS::Ace::NG {
110
111 const std::set<std::string> FrameNode::layoutTags_ = { "Flex", "Stack", "Row", "Column", "WindowScene", "root",
112 "__Common__", "Swiper", "Grid", "GridItem", "page", "stage", "FormComponent", "Tabs", "TabContent" };
113
114 class FrameNode::FrameProxy final : public RecursiveLock {
115 public:
116 struct FrameChildNode {
117 RefPtr<UINode> node;
118 uint32_t startIndex = 0;
119 uint32_t count = 0;
120 };
121
Lock()122 void Lock() override
123 {
124 ++inUse_;
125 }
126
Unlock()127 void Unlock() override
128 {
129 --inUse_;
130 if (!inUse_ && delayReset_) {
131 auto it = &hostNode_->frameProxy_;
132 while ((*it)) {
133 if (this == (*it)->prevFrameProxy_.get()) {
134 auto me = std::move((*it)->prevFrameProxy_);
135 (*it)->prevFrameProxy_ = std::move(me->prevFrameProxy_);
136 break;
137 }
138 it = &(*it)->prevFrameProxy_;
139 }
140 }
141 }
142
GetGuard()143 RecursionGuard GetGuard()
144 {
145 return RecursionGuard(*this);
146 }
147
FrameProxy(FrameNode * frameNode)148 explicit FrameProxy(FrameNode* frameNode) : hostNode_(frameNode)
149 {
150 prevFrameProxy_ = std::move(hostNode_->frameProxy_);
151 if (prevFrameProxy_ && !prevFrameProxy_->needResetChild_) {
152 children_ = prevFrameProxy_->children_;
153 cursor_ = children_.end();
154 if (prevFrameProxy_->cursor_ != prevFrameProxy_->children_.end()) {
155 cursor_ = std::find_if(children_.begin(), children_.end(),
156 [this](FrameChildNode& node) { return prevFrameProxy_->cursor_->node == node.node; });
157 }
158 }
159 }
160
Build()161 void Build()
162 {
163 if (hostNode_ == nullptr || !children_.empty()) {
164 return;
165 }
166 totalCount_ = 0;
167 auto children = hostNode_->GetChildren();
168 int32_t startIndex = 0;
169 int32_t count = 0;
170 for (const auto& child : children) {
171 count = child->FrameCount();
172 child->SetNodeIndexOffset(startIndex, count);
173 children_.push_back({ child, startIndex, count });
174 startIndex += count;
175 totalCount_ += count;
176 }
177 cursor_ = children_.begin();
178 }
179
AddFrameNode(const RefPtr<UINode> & UiNode,std::list<RefPtr<LayoutWrapper>> & allFrameNodeChildren,std::map<uint32_t,RefPtr<LayoutWrapper>> & partFrameNodeChildren,uint32_t & count)180 static void AddFrameNode(const RefPtr<UINode>& UiNode, std::list<RefPtr<LayoutWrapper>>& allFrameNodeChildren,
181 std::map<uint32_t, RefPtr<LayoutWrapper>>& partFrameNodeChildren, uint32_t& count)
182 {
183 auto frameNode = AceType::DynamicCast<FrameNode>(UiNode);
184 if (frameNode) {
185 allFrameNodeChildren.emplace_back(frameNode);
186 partFrameNodeChildren[count++] = frameNode;
187 return;
188 }
189 auto lazyForEachNode = AceType::DynamicCast<LazyForEachNode>(UiNode);
190 auto repeatVirtualScrollNode = AceType::DynamicCast<RepeatVirtualScrollNode>(UiNode);
191 if (lazyForEachNode) {
192 lazyForEachNode->BuildAllChildren();
193 } else if (repeatVirtualScrollNode) {
194 TAG_LOGE(AceLogTag::ACE_REPEAT, "repeatVirtualScroll not support in non scoll container!");
195 } else {
196 auto customNode = AceType::DynamicCast<CustomNode>(UiNode);
197 if (customNode) {
198 customNode->Render();
199 }
200 }
201 for (const auto& child : UiNode->GetChildren()) {
202 auto frameNode = AceType::DynamicCast<FrameNode>(child);
203 if (frameNode) {
204 allFrameNodeChildren.emplace_back(frameNode);
205 partFrameNodeChildren[count++] = frameNode;
206 continue;
207 }
208 AddFrameNode(child, allFrameNodeChildren, partFrameNodeChildren, count);
209 }
210 }
211
GetAllFrameChildren()212 ChildrenListWithGuard GetAllFrameChildren()
213 {
214 auto guard = GetGuard();
215 if (allFrameNodeChildren_.empty()) {
216 Build();
217 uint32_t count = 0;
218 for (const auto& child : children_) {
219 AddFrameNode(child.node, allFrameNodeChildren_, partFrameNodeChildren_, count);
220 }
221 }
222 return ChildrenListWithGuard(allFrameNodeChildren_, *this);
223 }
224
GetCurrentFrameChildren()225 ChildrenListWithGuard GetCurrentFrameChildren()
226 {
227 auto guard = GetGuard();
228 return ChildrenListWithGuard(allFrameNodeChildren_, *this);
229 }
230
FindFrameNodeByIndex(uint32_t index,bool needBuild,bool isCache,bool addToRenderTree)231 RefPtr<LayoutWrapper> FindFrameNodeByIndex(uint32_t index, bool needBuild, bool isCache, bool addToRenderTree)
232 {
233 while (cursor_ != children_.end()) {
234 if (cursor_->startIndex > index) {
235 cursor_--;
236 continue;
237 }
238
239 if (cursor_->startIndex + cursor_->count > index) {
240 auto frameNode = AceType::DynamicCast<FrameNode>(cursor_->node->GetFrameChildByIndex(
241 index - cursor_->startIndex, needBuild, isCache, addToRenderTree));
242 return frameNode;
243 }
244 cursor_++;
245 if (cursor_ == children_.end()) {
246 cursor_ = children_.begin();
247 return nullptr;
248 }
249 }
250 return nullptr;
251 }
252
GetFrameNodeByIndex(uint32_t index,bool needBuild,bool isCache,bool addToRenderTree)253 RefPtr<LayoutWrapper> GetFrameNodeByIndex(uint32_t index, bool needBuild, bool isCache, bool addToRenderTree)
254 {
255 auto itor = partFrameNodeChildren_.find(index);
256 if (itor == partFrameNodeChildren_.end()) {
257 Build();
258 auto child = FindFrameNodeByIndex(index, needBuild, isCache, addToRenderTree);
259 if (child && !isCache) {
260 partFrameNodeChildren_[index] = child;
261 }
262 return child;
263 }
264 return itor->second;
265 }
266
267 /**
268 * @brief Find child's index in parent's map. Only works on children that are already created and recorded.
269 *
270 * @param target child LayoutWrapper
271 * @return index of children
272 */
GetChildIndex(const RefPtr<LayoutWrapper> & target) const273 int32_t GetChildIndex(const RefPtr<LayoutWrapper>& target) const
274 {
275 for (auto it : partFrameNodeChildren_) {
276 if (it.second == target) {
277 return it.first;
278 }
279 }
280 return -1;
281 }
282
ResetChildren(bool needResetChild=false)283 void ResetChildren(bool needResetChild = false)
284 {
285 if (inUse_) {
286 LOGF(
287 "[%{public}d:%{public}s] reset children while in use", hostNode_->GetId(), hostNode_->GetTag().c_str());
288 if (SystemProperties::GetLayoutDetectEnabled()) {
289 abort();
290 }
291 delayReset_ = true;
292 needResetChild_ = needResetChild;
293 hostNode_->frameProxy_ = std::make_unique<FrameProxy>(hostNode_);
294 return;
295 }
296 auto guard = GetGuard();
297 delayReset_ = false;
298 allFrameNodeChildren_.clear();
299 partFrameNodeChildren_.clear();
300 totalCount_ = 0;
301 if (needResetChild) {
302 children_.clear();
303 cursor_ = children_.begin();
304 }
305 }
306
RemoveChildInRenderTree(uint32_t index)307 void RemoveChildInRenderTree(uint32_t index)
308 {
309 auto itor = partFrameNodeChildren_.find(index);
310 if (itor == partFrameNodeChildren_.end()) {
311 return;
312 }
313 itor->second->SetActive(false);
314 partFrameNodeChildren_.erase(itor);
315 while (cursor_ != children_.end()) {
316 if (cursor_->startIndex > index) {
317 cursor_--;
318 continue;
319 }
320 if (cursor_->startIndex + cursor_->count > index) {
321 cursor_->node->DoRemoveChildInRenderTree(index - cursor_->startIndex);
322 return;
323 }
324 cursor_++;
325 if (cursor_ == children_.end()) {
326 cursor_ = children_.begin();
327 return;
328 }
329 }
330 }
331
SetActiveChildRange(int32_t start,int32_t end,int32_t cacheStart,int32_t cacheEnd,bool showCache=false)332 void SetActiveChildRange(int32_t start, int32_t end, int32_t cacheStart, int32_t cacheEnd, bool showCache = false)
333 {
334 int32_t startIndex = showCache ? start - cacheStart : start;
335 int32_t endIndex = showCache ? end + cacheEnd : end;
336 for (auto itor = partFrameNodeChildren_.begin(); itor != partFrameNodeChildren_.end();) {
337 int32_t index = itor->first;
338 if ((startIndex <= endIndex && index >= startIndex && index <= endIndex) ||
339 (startIndex > endIndex && (index <= endIndex || startIndex <= index))) {
340 itor++;
341 } else {
342 itor = partFrameNodeChildren_.erase(itor);
343 }
344 }
345 auto guard = GetGuard();
346 for (const auto& child : children_) {
347 child.node->DoSetActiveChildRange(
348 start - child.startIndex, end - child.startIndex, cacheStart, cacheEnd, showCache);
349 }
350 }
351
SetActiveChildRange(const std::optional<ActiveChildSets> & activeChildSets,const std::optional<ActiveChildRange> & activeChildRange)352 void SetActiveChildRange(
353 const std::optional<ActiveChildSets>& activeChildSets, const std::optional<ActiveChildRange>& activeChildRange)
354 {
355 if (!activeChildSets.has_value()) {
356 return;
357 }
358 for (auto itor = partFrameNodeChildren_.begin(); itor != partFrameNodeChildren_.end();) {
359 int32_t index = itor->first;
360 if (activeChildSets->activeItems.find(index) != activeChildSets->activeItems.end()) {
361 itor++;
362 } else {
363 itor = partFrameNodeChildren_.erase(itor);
364 }
365 }
366 auto guard = GetGuard();
367 // repeat node will use active node sets, V1 node(as lazyforeach) will still use active ndoe range.
368 for (const auto& child : children_) {
369 if (child.node->GetTag() == V2::JS_REPEAT_ETS_TAG) {
370 child.node->DoSetActiveChildRange(
371 activeChildSets->activeItems, activeChildSets->cachedItems, child.startIndex);
372 } else if (activeChildRange.has_value()) {
373 child.node->DoSetActiveChildRange(activeChildRange->start - child.startIndex,
374 activeChildRange->end - child.startIndex, activeChildRange->cacheStart, activeChildRange->cacheEnd);
375 }
376 }
377 }
378
RecycleItemsByIndex(uint32_t start,uint32_t end)379 void RecycleItemsByIndex(uint32_t start, uint32_t end)
380 {
381 for (auto it = partFrameNodeChildren_.begin(); it != partFrameNodeChildren_.end();) {
382 if (it->first >= start && it->first < end) {
383 it = partFrameNodeChildren_.erase(it);
384 } else {
385 it++;
386 }
387 }
388 }
389
RemoveAllChildInRenderTreeAfterReset()390 void RemoveAllChildInRenderTreeAfterReset()
391 {
392 Build();
393 auto guard = GetGuard();
394 for (const auto& child : children_) {
395 child.node->DoRemoveChildInRenderTree(0, true);
396 }
397 }
398
RemoveAllChildInRenderTree()399 void RemoveAllChildInRenderTree()
400 {
401 SetAllChildrenInactive();
402 ResetChildren();
403 hostNode_->frameProxy_->RemoveAllChildInRenderTreeAfterReset();
404 }
405
GetTotalCount()406 uint32_t GetTotalCount()
407 {
408 return totalCount_;
409 }
410
SetAllChildrenInactive()411 void SetAllChildrenInactive()
412 {
413 auto guard = GetGuard();
414 for (const auto& child : partFrameNodeChildren_) {
415 child.second->SetActive(false);
416 }
417 }
418
Dump()419 std::string Dump()
420 {
421 if (totalCount_ == 0) {
422 return "totalCount is 0";
423 }
424 std::string info = "FrameChildNode:[";
425 auto guard = GetGuard();
426 for (const auto& child : children_) {
427 info += std::to_string(child.node->GetId());
428 info += "-";
429 info += std::to_string(child.startIndex);
430 info += "-";
431 info += std::to_string(child.count);
432 info += ",";
433 }
434 info += "] partFrameNodeChildren:[";
435 for (const auto& child : partFrameNodeChildren_) {
436 info += std::to_string(child.second->GetHostNode()->GetId());
437 info += ",";
438 }
439 info += "] TotalCount:";
440 info += std::to_string(totalCount_);
441 return info;
442 }
443
SetCacheCount(int32_t cacheCount,const std::optional<LayoutConstraintF> & itemConstraint)444 void SetCacheCount(int32_t cacheCount, const std::optional<LayoutConstraintF>& itemConstraint)
445 {
446 auto guard = GetGuard();
447 for (const auto& child : children_) {
448 child.node->OnSetCacheCount(cacheCount, itemConstraint);
449 }
450 }
451
452 private:
453 std::list<FrameChildNode> children_;
454 std::list<FrameChildNode>::iterator cursor_ = children_.begin();
455 std::list<RefPtr<LayoutWrapper>> allFrameNodeChildren_;
456 std::map<uint32_t, RefPtr<LayoutWrapper>> partFrameNodeChildren_;
457 std::unique_ptr<FrameProxy> prevFrameProxy_;
458 int32_t totalCount_ = 0;
459 FrameNode* hostNode_ { nullptr };
460 uint32_t inUse_ = 0;
461 bool delayReset_ = false;
462 bool needResetChild_ = false;
463 }; // namespace OHOS::Ace::NG
464
FrameNode(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern,bool isRoot,bool isLayoutNode)465 FrameNode::FrameNode(
466 const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern, bool isRoot, bool isLayoutNode)
467 : UINode(tag, nodeId, isRoot), LayoutWrapper(WeakClaim(this)), pattern_(pattern)
468 {
469 isLayoutNode_ = isLayoutNode;
470 frameProxy_ = std::make_unique<FrameProxy>(this);
471 renderContext_->InitContext(IsRootNode(), pattern_->GetContextParam(), isLayoutNode);
472 paintProperty_ = pattern->CreatePaintProperty();
473 layoutProperty_ = pattern->CreateLayoutProperty();
474 eventHub_ = pattern->CreateEventHub();
475 accessibilityProperty_ = pattern->CreateAccessibilityProperty();
476 // first create make layout property dirty.
477 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
478 layoutProperty_->SetHost(WeakClaim(this));
479 layoutSeperately_ = true;
480 }
481
~FrameNode()482 FrameNode::~FrameNode()
483 {
484 ResetPredictNodes();
485 for (const auto& destroyCallback : destroyCallbacks_) {
486 destroyCallback();
487 }
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 if (eventHub_) {
503 eventHub_->ClearOnAreaChangedInnerCallbacks();
504 if (eventHub_->HasVisibleAreaCallback(true) || eventHub_->HasVisibleAreaCallback(false)) {
505 SetVisibleAreaChangeTriggerReason(VisibleAreaChangeTriggerReason::FRAMENODE_DESTROY);
506 TriggerVisibleAreaChangeCallback(0, true);
507 CleanVisibleAreaUserCallback();
508 CleanVisibleAreaInnerCallback();
509 }
510 }
511 auto pipeline = PipelineContext::GetCurrentContext();
512 if (pipeline) {
513 pipeline->RemoveOnAreaChangeNode(GetId());
514 pipeline->RemoveVisibleAreaChangeNode(GetId());
515 pipeline->ChangeMouseStyle(GetId(), MouseFormat::DEFAULT);
516 pipeline->FreeMouseStyleHoldNode(GetId());
517 pipeline->RemoveStoredNode(GetRestoreId());
518 auto dragManager = pipeline->GetDragDropManager();
519 if (dragManager) {
520 dragManager->RemoveDragFrameNode(GetId());
521 dragManager->UnRegisterDragStatusListener(GetId());
522 }
523 auto frameRateManager = pipeline->GetFrameRateManager();
524 if (frameRateManager) {
525 frameRateManager->RemoveNodeRate(GetId());
526 }
527 pipeline->RemoveChangedFrameNode(GetId());
528 pipeline->RemoveFrameNodeChangeListener(GetId());
529 }
530 FireOnNodeDestroyCallback();
531 FireFrameNodeDestructorCallback();
532 }
533
CreateFrameNodeWithTree(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern)534 RefPtr<FrameNode> FrameNode::CreateFrameNodeWithTree(
535 const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern)
536 {
537 auto newChild = CreateFrameNode(tag, nodeId, pattern, true);
538 newChild->SetDepth(1);
539 return newChild;
540 }
541
GetOrCreateFrameNode(const std::string & tag,int32_t nodeId,const std::function<RefPtr<Pattern> (void)> & patternCreator)542 RefPtr<FrameNode> FrameNode::GetOrCreateFrameNode(
543 const std::string& tag, int32_t nodeId, const std::function<RefPtr<Pattern>(void)>& patternCreator)
544 {
545 auto frameNode = GetFrameNode(tag, nodeId);
546 if (frameNode) {
547 return frameNode;
548 }
549 auto pattern = patternCreator ? patternCreator() : MakeRefPtr<Pattern>();
550 return CreateFrameNode(tag, nodeId, pattern);
551 }
552
GetOrCreateCommonNode(const std::string & tag,int32_t nodeId,bool isLayoutNode,const std::function<RefPtr<Pattern> (void)> & patternCreator)553 RefPtr<FrameNode> FrameNode::GetOrCreateCommonNode(const std::string& tag, int32_t nodeId, bool isLayoutNode,
554 const std::function<RefPtr<Pattern>(void)>& patternCreator)
555 {
556 auto commonNode = GetFrameNode(tag, nodeId);
557 if (commonNode) {
558 commonNode->isLayoutNode_ = isLayoutNode;
559 return commonNode;
560 }
561 auto pattern = patternCreator ? patternCreator() : MakeRefPtr<Pattern>();
562 return CreateCommonNode(tag, nodeId, isLayoutNode, pattern);
563 }
564
GetFrameNode(const std::string & tag,int32_t nodeId)565 RefPtr<FrameNode> FrameNode::GetFrameNode(const std::string& tag, int32_t nodeId)
566 {
567 auto frameNode = ElementRegister::GetInstance()->GetSpecificItemById<FrameNode>(nodeId);
568 CHECK_NULL_RETURN(frameNode, nullptr);
569 if (frameNode->GetTag() != tag) {
570 ElementRegister::GetInstance()->RemoveItemSilently(nodeId);
571 auto parent = frameNode->GetParent();
572 if (parent) {
573 parent->RemoveChild(frameNode);
574 }
575 return nullptr;
576 }
577 return frameNode;
578 }
579
CreateFrameNode(const std::string & tag,int32_t nodeId,const RefPtr<Pattern> & pattern,bool isRoot)580 RefPtr<FrameNode> FrameNode::CreateFrameNode(
581 const std::string& tag, int32_t nodeId, const RefPtr<Pattern>& pattern, bool isRoot)
582 {
583 auto frameNode = MakeRefPtr<FrameNode>(tag, nodeId, pattern, isRoot);
584 ElementRegister::GetInstance()->AddUINode(frameNode);
585 frameNode->InitializePatternAndContext();
586 return frameNode;
587 }
588
CreateCommonNode(const std::string & tag,int32_t nodeId,bool isLayoutNode,const RefPtr<Pattern> & pattern,bool isRoot)589 RefPtr<FrameNode> FrameNode::CreateCommonNode(
590 const std::string& tag, int32_t nodeId, bool isLayoutNode, const RefPtr<Pattern>& pattern, bool isRoot)
591 {
592 auto frameNode = MakeRefPtr<FrameNode>(tag, nodeId, pattern, isRoot, isLayoutNode);
593 ElementRegister::GetInstance()->AddUINode(frameNode);
594 frameNode->InitializePatternAndContext();
595 return frameNode;
596 }
597
GetIsLayoutNode()598 bool FrameNode::GetIsLayoutNode()
599 {
600 return isLayoutNode_;
601 }
602
GetIsFind()603 bool FrameNode::GetIsFind()
604 {
605 return isFind_;
606 }
607
SetIsFind(bool isFind)608 void FrameNode::SetIsFind(bool isFind)
609 {
610 isFind_ = isFind;
611 }
612
GetOneDepthVisibleFrame(std::list<RefPtr<FrameNode>> & children)613 void FrameNode::GetOneDepthVisibleFrame(std::list<RefPtr<FrameNode>>& children)
614 {
615 GenerateOneDepthVisibleFrameWithTransition(children);
616 if (overlayNode_) {
617 children.emplace_back(overlayNode_);
618 }
619 }
620
GetOneDepthVisibleFrameWithOffset(std::list<RefPtr<FrameNode>> & children,OffsetF & offset)621 void FrameNode::GetOneDepthVisibleFrameWithOffset(std::list<RefPtr<FrameNode>>& children, OffsetF& offset)
622 {
623 auto context = GetRenderContext();
624 CHECK_NULL_VOID(context);
625 offset += context->GetPaintRectWithoutTransform().GetOffset();
626 GenerateOneDepthVisibleFrameWithOffset(children, offset);
627 if (overlayNode_) {
628 children.emplace_back(overlayNode_);
629 }
630 }
631
IsSupportDrawModifier()632 bool FrameNode::IsSupportDrawModifier()
633 {
634 CHECK_NULL_RETURN(pattern_, false);
635 return pattern_->IsSupportDrawModifier();
636 }
637
ProcessOffscreenNode(const RefPtr<FrameNode> & node)638 void FrameNode::ProcessOffscreenNode(const RefPtr<FrameNode>& node)
639 {
640 CHECK_NULL_VOID(node);
641 auto task = [weak = AceType::WeakClaim(AceType::RawPtr(node))] () {
642 auto node = weak.Upgrade();
643 CHECK_NULL_VOID(node);
644 node->ProcessOffscreenTask();
645 node->MarkModifyDone();
646 node->UpdateLayoutPropertyFlag();
647 node->SetActive();
648 node->isLayoutDirtyMarked_ = true;
649 auto pipeline = node->GetContext();
650 if (pipeline) {
651 pipeline->FlushUITaskWithSingleDirtyNode(node);
652 }
653 auto predictLayoutNode = std::move(node->predictLayoutNode_);
654 for (auto& node : predictLayoutNode) {
655 auto frameNode = node.Upgrade();
656 if (frameNode && pipeline) {
657 pipeline->FlushUITaskWithSingleDirtyNode(frameNode);
658 }
659 }
660 if (pipeline) {
661 pipeline->FlushSyncGeometryNodeTasks();
662 }
663
664 auto paintProperty = node->GetPaintProperty<PaintProperty>();
665 auto wrapper = node->CreatePaintWrapper();
666 if (wrapper != nullptr) {
667 wrapper->FlushRender();
668 }
669 paintProperty->CleanDirty();
670 CHECK_NULL_VOID(pipeline);
671 pipeline->FlushMessages();
672 node->SetActive(false);
673 };
674 auto pipeline = node->GetContext();
675 if (pipeline && pipeline->IsLayouting()) {
676 pipeline->AddAfterLayoutTask(task);
677 return;
678 }
679 task();
680 }
681
InitializePatternAndContext()682 void FrameNode::InitializePatternAndContext()
683 {
684 eventHub_->AttachHost(WeakClaim(this));
685 pattern_->AttachToFrameNode(WeakClaim(this));
686 accessibilityProperty_->SetHost(WeakClaim(this));
687 renderContext_->SetRequestFrame([weak = WeakClaim(this)] {
688 auto frameNode = weak.Upgrade();
689 CHECK_NULL_VOID(frameNode);
690 if (frameNode->IsOnMainTree()) {
691 auto context = frameNode->GetContext();
692 CHECK_NULL_VOID(context);
693 context->RequestFrame();
694 return;
695 }
696 frameNode->hasPendingRequest_ = true;
697 });
698 renderContext_->SetHostNode(WeakClaim(this));
699 // Initialize FocusHub
700 if (pattern_->GetFocusPattern().GetFocusType() != FocusType::DISABLE) {
701 GetOrCreateFocusHub();
702 }
703 }
704
DumpSafeAreaInfo()705 void FrameNode::DumpSafeAreaInfo()
706 {
707 auto&& opts = layoutProperty_->GetSafeAreaExpandOpts();
708 if (opts) {
709 DumpLog::GetInstance().AddDesc(layoutProperty_->GetSafeAreaExpandOpts()
710 ->ToString()
711 .append(",hostPageId: ")
712 .append(std::to_string(GetPageId()).c_str()));
713 }
714 if (layoutProperty_->GetSafeAreaInsets()) {
715 DumpLog::GetInstance().AddDesc(layoutProperty_->GetSafeAreaInsets()->ToString());
716 }
717 if (SelfOrParentExpansive()) {
718 DumpLog::GetInstance().AddDesc(std::string("selfAdjust: ")
719 .append(geometryNode_->GetSelfAdjust().ToString().c_str())
720 .append(",parentAdjust: ")
721 .append(geometryNode_->GetParentAdjust().ToString().c_str()));
722 }
723 CHECK_NULL_VOID(GetTag() == V2::PAGE_ETS_TAG);
724 auto pipeline = GetContext();
725 CHECK_NULL_VOID(pipeline);
726 auto manager = pipeline->GetSafeAreaManager();
727 CHECK_NULL_VOID(manager);
728 DumpLog::GetInstance().AddDesc(std::string("ignoreSafeArea: ")
729 .append(std::to_string(manager->IsIgnoreAsfeArea()))
730 .append(std::string(", isNeedAvoidWindow: ").c_str())
731 .append(std::to_string(manager->IsNeedAvoidWindow()))
732 .append(std::string(", isFullScreen: ").c_str())
733 .append(std::to_string(manager->IsFullScreen()))
734 .append(std::string(", isKeyboardAvoidMode").c_str())
735 .append(std::to_string(static_cast<int32_t>(manager->GetKeyBoardAvoidMode())))
736 .append(std::string(", isUseCutout").c_str())
737 .append(std::to_string(pipeline->GetUseCutout())));
738 }
739
DumpAlignRulesInfo()740 void FrameNode::DumpAlignRulesInfo()
741 {
742 auto& flexItemProperties = layoutProperty_->GetFlexItemProperty();
743 CHECK_NULL_VOID(flexItemProperties);
744 auto rulesToString = flexItemProperties->AlignRulesToString();
745 CHECK_NULL_VOID(!rulesToString.empty());
746 DumpLog::GetInstance().AddDesc(std::string("AlignRules: ").append(rulesToString));
747 }
748
DumpExtensionHandlerInfo()749 void FrameNode::DumpExtensionHandlerInfo()
750 {
751 if (!extensionHandler_) {
752 return;
753 }
754 DumpLog::GetInstance().AddDesc(std::string("ExtensionHandler: HasCustomerMeasure: ")
755 .append(extensionHandler_->HasCustomerMeasure() ? "true" : "false")
756 .append(", HasCustomerLayout: ")
757 .append(extensionHandler_->HasCustomerLayout() ? "true" : "false"));
758 }
759
DumpCommonInfo()760 void FrameNode::DumpCommonInfo()
761 {
762 DumpLog::GetInstance().AddDesc(std::string("FrameRect: ").append(geometryNode_->GetFrameRect().ToString()));
763 DumpLog::GetInstance().AddDesc(
764 std::string("PaintRect without transform: ").append(renderContext_->GetPaintRectWithoutTransform().ToString()));
765 if (renderContext_->GetBackgroundColor()->ColorToString().compare("#00000000") != 0) {
766 DumpLog::GetInstance().AddDesc(
767 std::string("BackgroundColor: ").append(renderContext_->GetBackgroundColor()->ColorToString()));
768 }
769 if (geometryNode_->GetParentLayoutConstraint().has_value()) {
770 DumpLog::GetInstance().AddDesc(std::string("ParentLayoutConstraint: ")
771 .append(geometryNode_->GetParentLayoutConstraint().value().ToString()));
772 }
773 DumpLog::GetInstance().AddDesc(std::string("top: ")
774 .append(std::to_string(GetOffsetRelativeToWindow().GetY()))
775 .append(" left: ")
776 .append(std::to_string(GetOffsetRelativeToWindow().GetX())));
777 if (static_cast<int32_t>(IsActive()) != 1) {
778 DumpLog::GetInstance().AddDesc(
779 std::string("Active: ").append(std::to_string(static_cast<int32_t>(IsActive()))));
780 }
781 if (IsFreeze()) {
782 DumpLog::GetInstance().AddDesc(std::string("Freeze: 1"));
783 }
784 if (static_cast<int32_t>(layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)) != 0) {
785 DumpLog::GetInstance().AddDesc(std::string("Visible: ")
786 .append(std::to_string(static_cast<int32_t>(
787 layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)))));
788 }
789 if (layoutProperty_->GetPaddingProperty()) {
790 DumpLog::GetInstance().AddDesc(
791 std::string("Padding: ").append(layoutProperty_->GetPaddingProperty()->ToString().c_str()));
792 }
793 if (layoutProperty_->GetSafeAreaPaddingProperty()) {
794 DumpLog::GetInstance().AddDesc(std::string("SafeArea Padding: ")
795 .append(layoutProperty_->GetSafeAreaPaddingProperty()->ToString().c_str()));
796 }
797 if (layoutProperty_->GetBorderWidthProperty()) {
798 DumpLog::GetInstance().AddDesc(
799 std::string("Border: ").append(layoutProperty_->GetBorderWidthProperty()->ToString().c_str()));
800 }
801 if (layoutProperty_->GetMarginProperty()) {
802 DumpLog::GetInstance().AddDesc(
803 std::string("Margin: ").append(layoutProperty_->GetMarginProperty()->ToString().c_str()));
804 }
805 if (layoutProperty_->GetLayoutRect()) {
806 DumpLog::GetInstance().AddDesc(
807 std::string("LayoutRect: ").append(layoutProperty_->GetLayoutRect().value().ToString().c_str()));
808 }
809 DumpExtensionHandlerInfo();
810 DumpSafeAreaInfo();
811 if (layoutProperty_->GetCalcLayoutConstraint()) {
812 DumpLog::GetInstance().AddDesc(std::string("User defined constraint: ")
813 .append(layoutProperty_->GetCalcLayoutConstraint()->ToString().c_str()));
814 }
815 if (!propInspectorId_->empty()) {
816 DumpLog::GetInstance().AddDesc(std::string("compid: ").append(propInspectorId_.value_or("")));
817 }
818 if (layoutProperty_->GetPaddingProperty() || layoutProperty_->GetBorderWidthProperty() ||
819 layoutProperty_->GetMarginProperty() || layoutProperty_->GetCalcLayoutConstraint()) {
820 DumpLog::GetInstance().AddDesc(
821 std::string("ContentConstraint: ")
822 .append(layoutProperty_->GetContentLayoutConstraint().has_value()
823 ? layoutProperty_->GetContentLayoutConstraint().value().ToString()
824 : "NA"));
825 }
826 if (GetTag() == V2::ROOT_ETS_TAG) {
827 auto pipeline = GetContext();
828 CHECK_NULL_VOID(pipeline);
829 DumpLog::GetInstance().AddDesc(std::string("dpi: ").append(std::to_string(pipeline->GetDensity())));
830 }
831 DumpAlignRulesInfo();
832 DumpDragInfo();
833 DumpOverlayInfo();
834 if (frameProxy_->Dump().compare("totalCount is 0") != 0) {
835 DumpLog::GetInstance().AddDesc(std::string("FrameProxy: ").append(frameProxy_->Dump().c_str()));
836 }
837 if (isRemoving_) {
838 DumpLog::GetInstance().AddDesc(std::string("IsRemoving: True"));
839 }
840 }
841
DumpDragInfo()842 void FrameNode::DumpDragInfo()
843 {
844 DumpLog::GetInstance().AddDesc("------------start print dragInfo");
845 DumpLog::GetInstance().AddDesc(std::string("Draggable: ")
846 .append(draggable_ ? "true" : "false")
847 .append(" UserSet: ")
848 .append(userSet_ ? "true" : "false")
849 .append(" CustomerSet: ")
850 .append(customerSet_ ? "true" : "false"));
851 auto dragPreviewStr =
852 std::string("DragPreview: Has customNode: ").append(dragPreviewInfo_.customNode ? "YES" : "NO");
853 dragPreviewStr.append(" Has pixelMap: ").append(dragPreviewInfo_.pixelMap ? "YES" : "NO");
854 dragPreviewStr.append(" extraInfo: ").append(dragPreviewInfo_.extraInfo.c_str());
855 dragPreviewStr.append(" inspectorId: ").append(dragPreviewInfo_.inspectorId.c_str());
856 DumpLog::GetInstance().AddDesc(dragPreviewStr);
857 auto eventHub = GetEventHub<EventHub>();
858 DumpLog::GetInstance().AddDesc(std::string("Event: ")
859 .append("OnDragStart: ")
860 .append(eventHub->HasOnDragStart() ? "YES" : "NO")
861 .append(" OnDragEnter: ")
862 .append(eventHub->HasOnDragEnter() ? "YES" : "NO")
863 .append(" OnDragLeave: ")
864 .append(eventHub->HasOnDragLeave() ? "YES" : "NO")
865 .append(" OnDragMove: ")
866 .append(eventHub->HasOnDragMove() ? "YES" : "NO")
867 .append(" OnDrop: ")
868 .append(eventHub->HasOnDrop() ? "YES" : "NO")
869 .append(" OnDragEnd: ")
870 .append(eventHub->HasOnDragEnd() ? "YES" : "NO"));
871 DumpLog::GetInstance().AddDesc(std::string("DefaultOnDragStart: ")
872 .append(eventHub->HasDefaultOnDragStart() ? "YES" : "NO")
873 .append(" CustomerOnDragEnter: ")
874 .append(eventHub->HasCustomerOnDragEnter() ? "YES" : "NO")
875 .append(" CustomerOnDragLeave: ")
876 .append(eventHub->HasCustomerOnDragLeave() ? "YES" : "NO")
877 .append(" CustomerOnDragMove: ")
878 .append(eventHub->HasCustomerOnDragMove() ? "YES" : "NO")
879 .append(" CustomerOnDrop: ")
880 .append(eventHub->HasCustomerOnDrop() ? "YES" : "NO")
881 .append(" CustomerOnDragEnd: ")
882 .append(eventHub->HasCustomerOnDragEnd() ? "YES" : "NO"));
883 DumpLog::GetInstance().AddDesc("------------end print dragInfo");
884 }
885
DumpOnSizeChangeInfo()886 void FrameNode::DumpOnSizeChangeInfo()
887 {
888 for (auto it = onSizeChangeDumpInfos.rbegin(); it != onSizeChangeDumpInfos.rend(); ++it) {
889 DumpLog::GetInstance().AddDesc(std::string("onSizeChange Time: ")
890 .append(ConvertTimestampToStr(it->onSizeChangeTimeStamp))
891 .append(" lastFrameRect: ")
892 .append(it->lastFrameRect.ToString())
893 .append(" currFrameRect: ")
894 .append(it->currFrameRect.ToString()));
895 }
896 }
897
DumpKeyboardShortcutInfo()898 void FrameNode::DumpKeyboardShortcutInfo()
899 {
900 auto eventHub = GetEventHub<EventHub>();
901 if (!eventHub) {
902 return;
903 }
904 auto keyboardShortcuts = eventHub->GetKeyboardShortcut();
905 std::string result;
906 for (auto& keyboardShortcut : keyboardShortcuts) {
907 result.append("KeyboardShortcut: ")
908 .append("keys: ")
909 .append(std::to_string(keyboardShortcut.keys))
910 .append(" value: ")
911 .append(keyboardShortcut.value);
912 }
913 DumpLog::GetInstance().AddDesc(result);
914 }
915
DumpOverlayInfo()916 void FrameNode::DumpOverlayInfo()
917 {
918 if (!layoutProperty_->IsOverlayNode()) {
919 return;
920 }
921 DumpLog::GetInstance().AddDesc(std::string("IsOverlayNode: ").append(std::string("true")));
922 Dimension offsetX, offsetY;
923 layoutProperty_->GetOverlayOffset(offsetX, offsetY);
924 DumpLog::GetInstance().AddDesc(
925 std::string("OverlayOffset: ").append(offsetX.ToString()).append(std::string(", ")).append(offsetY.ToString()));
926 }
927
DumpSimplifyCommonInfo(std::unique_ptr<JsonValue> & json)928 void FrameNode::DumpSimplifyCommonInfo(std::unique_ptr<JsonValue>& json)
929 {
930 if (geometryNode_) {
931 if (geometryNode_->GetFrameRect() != RectF(0.0, 0.0, 0.0, 0.0)) {
932 json->Put("FrameRect", geometryNode_->GetFrameRect().ToString().c_str());
933 }
934 if (geometryNode_->GetParentLayoutConstraint().has_value()) {
935 json->Put("ParentLayoutConstraint", geometryNode_->GetParentLayoutConstraint().value().ToString().c_str());
936 }
937 auto offset = GetOffsetRelativeToWindow();
938 if (offset != OffsetF(0.0, 0.0)) {
939 std::stringstream stream;
940 stream << std::fixed << std::setprecision(DEFAULT_PRECISION) << offset.GetX() << "," << offset.GetY();
941 json->Put("Offset", stream.str().c_str());
942 }
943 }
944 if (renderContext_) {
945 if (renderContext_->GetPaintRectWithoutTransform() != RectF(0.0, 0.0, 0.0, 0.0)) {
946 json->Put("PaintRectWithoutTransform", renderContext_->GetPaintRectWithoutTransform().ToString().c_str());
947 }
948 if (renderContext_->GetBackgroundColor() &&
949 renderContext_->GetBackgroundColor()->ColorToString().compare("#00000000") != 0) {
950 json->Put("BackgroundColor", renderContext_->GetBackgroundColor()->ColorToString().c_str());
951 }
952 if (!NearZero(renderContext_->GetZIndexValue(ZINDEX_DEFAULT_VALUE))) {
953 json->Put("ZIndex: ", renderContext_->GetZIndexValue(ZINDEX_DEFAULT_VALUE));
954 }
955 }
956 if (layoutProperty_) {
957 VisibleType visible = layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE);
958 if (visible != VisibleType::VISIBLE) {
959 json->Put("Visible", static_cast<int32_t>(visible));
960 }
961 DumpPadding(layoutProperty_->GetPaddingProperty(), std::string("Padding"), json);
962 DumpBorder(layoutProperty_->GetBorderWidthProperty(), std::string("Border"), json);
963 DumpPadding(layoutProperty_->GetMarginProperty(), std::string("Margin"), json);
964 if (layoutProperty_->GetLayoutRect()) {
965 json->Put("LayoutRect", layoutProperty_->GetLayoutRect().value().ToString().c_str());
966 }
967 if (layoutProperty_->GetCalcLayoutConstraint()) {
968 json->Put("UserDefinedConstraint", layoutProperty_->GetCalcLayoutConstraint()->ToString().c_str());
969 }
970 if (layoutProperty_->GetPaddingProperty() || layoutProperty_->GetBorderWidthProperty() ||
971 layoutProperty_->GetMarginProperty() || layoutProperty_->GetCalcLayoutConstraint()) {
972 if (layoutProperty_->GetContentLayoutConstraint().has_value()) {
973 json->Put("ContentConstraint",
974 layoutProperty_->GetContentLayoutConstraint().value().ToString().c_str());
975 }
976 }
977 }
978 }
979
DumpPadding(const std::unique_ptr<NG::PaddingProperty> & padding,std::string label,std::unique_ptr<JsonValue> & json)980 void FrameNode::DumpPadding(const std::unique_ptr<NG::PaddingProperty>& padding, std::string label,
981 std::unique_ptr<JsonValue>& json)
982 {
983 CHECK_NULL_VOID(padding);
984 NG::CalcLength defaultValue = NG::CalcLength(
985 Dimension(0, padding->left.value_or(CalcLength()).GetDimension().Unit()));
986 if (padding->left.value_or(defaultValue) != defaultValue || padding->right.value_or(defaultValue) != defaultValue ||
987 padding->top.value_or(defaultValue) != defaultValue || padding->bottom.value_or(defaultValue) != defaultValue) {
988 json->Put(label.c_str(), padding->ToString().c_str());
989 }
990 }
991
DumpBorder(const std::unique_ptr<NG::BorderWidthProperty> & border,std::string label,std::unique_ptr<JsonValue> & json)992 void FrameNode::DumpBorder(const std::unique_ptr<NG::BorderWidthProperty>& border, std::string label,
993 std::unique_ptr<JsonValue>& json)
994 {
995 CHECK_NULL_VOID(border);
996 Dimension defaultValue(0, border->leftDimen.value_or(Dimension()).Unit());
997 if (border->leftDimen.value_or(defaultValue) != defaultValue ||
998 border->rightDimen.value_or(defaultValue) != defaultValue ||
999 border->topDimen.value_or(defaultValue) != defaultValue ||
1000 border->bottomDimen.value_or(defaultValue) != defaultValue) {
1001 json->Put(label.c_str(), border->ToString().c_str());
1002 }
1003 }
1004
DumpSimplifySafeAreaInfo(std::unique_ptr<JsonValue> & json)1005 void FrameNode::DumpSimplifySafeAreaInfo(std::unique_ptr<JsonValue>& json)
1006 {
1007 if (layoutProperty_) {
1008 auto&& opts = layoutProperty_->GetSafeAreaExpandOpts();
1009 if (opts && opts->type != NG::SAFE_AREA_TYPE_NONE && opts->edges != NG::SAFE_AREA_EDGE_NONE) {
1010 json->Put("SafeAreaExpandOpts", opts->ToString().c_str());
1011 }
1012 if (layoutProperty_->GetSafeAreaInsets()) {
1013 json->Put("SafeAreaInsets", layoutProperty_->GetSafeAreaInsets()->ToString().c_str());
1014 }
1015 }
1016 if (SelfOrParentExpansive()) {
1017 if (geometryNode_) {
1018 RectF defaultValue(0.0, 0.0, 0.0, 0.0);
1019 auto rect = geometryNode_->GetSelfAdjust();
1020 auto parentRect = geometryNode_->GetParentAdjust();
1021 if (rect != defaultValue) {
1022 json->Put("SelfAdjust", rect.ToString().c_str());
1023 }
1024 if (parentRect != defaultValue) {
1025 json->Put("ParentSelfAdjust", parentRect.ToString().c_str());
1026 }
1027 }
1028 CHECK_EQUAL_VOID(GetTag(), V2::PAGE_ETS_TAG);
1029 auto pipeline = GetContext();
1030 CHECK_NULL_VOID(pipeline);
1031 auto manager = pipeline->GetSafeAreaManager();
1032 CHECK_NULL_VOID(manager);
1033 if (!manager->IsIgnoreAsfeArea()) {
1034 json->Put("IgnoreSafeArea", manager->IsIgnoreAsfeArea());
1035 }
1036 if (!manager->IsNeedAvoidWindow()) {
1037 json->Put("IsNeedAvoidWindow", manager->IsNeedAvoidWindow());
1038 }
1039 if (!manager->IsFullScreen()) {
1040 json->Put("IsFullScreen", manager->IsFullScreen());
1041 }
1042 if (!manager->KeyboardSafeAreaEnabled()) {
1043 json->Put("IsKeyboardAvoidMode", static_cast<int32_t>(manager->GetKeyBoardAvoidMode()));
1044 }
1045 if (!pipeline->GetUseCutout()) {
1046 json->Put("IsUseCutout", pipeline->GetUseCutout());
1047 }
1048 }
1049 }
1050
DumpSimplifyOverlayInfo(std::unique_ptr<JsonValue> & json)1051 void FrameNode::DumpSimplifyOverlayInfo(std::unique_ptr<JsonValue>& json)
1052 {
1053 if (layoutProperty_ || !layoutProperty_->IsOverlayNode()) {
1054 return;
1055 }
1056 json->Put("IsOverlayNode", true);
1057 Dimension offsetX;
1058 Dimension offsetY;
1059 layoutProperty_->GetOverlayOffset(offsetX, offsetY);
1060 json->Put("OverlayOffset", (offsetX.ToString() + "," + offsetY.ToString()).c_str());
1061 }
1062
DumpSimplifyInfo(std::unique_ptr<JsonValue> & json)1063 void FrameNode::DumpSimplifyInfo(std::unique_ptr<JsonValue>& json)
1064 {
1065 CHECK_NULL_VOID(json);
1066 DumpSimplifyCommonInfo(json);
1067 DumpSimplifySafeAreaInfo(json);
1068 DumpSimplifyOverlayInfo(json);
1069 if (pattern_ && GetTag() == V2::UI_EXTENSION_COMPONENT_TAG) {
1070 pattern_->DumpInfo(json);
1071 }
1072 if (renderContext_) {
1073 auto renderContextJson = JsonUtil::Create();
1074 renderContext_->DumpSimplifyInfo(renderContextJson);
1075 json->PutRef("RenderContext", std::move(renderContextJson));
1076 }
1077 }
1078
DumpInfo()1079 void FrameNode::DumpInfo()
1080 {
1081 DumpCommonInfo();
1082 DumpOnSizeChangeInfo();
1083 DumpKeyboardShortcutInfo();
1084 if (pattern_) {
1085 pattern_->DumpInfo();
1086 }
1087 if (renderContext_) {
1088 renderContext_->DumpInfo();
1089 }
1090 }
1091
DumpAdvanceInfo()1092 void FrameNode::DumpAdvanceInfo()
1093 {
1094 DumpCommonInfo();
1095 DumpOnSizeChangeInfo();
1096 DumpKeyboardShortcutInfo();
1097 if (pattern_) {
1098 pattern_->DumpInfo();
1099 pattern_->DumpAdvanceInfo();
1100 }
1101 if (renderContext_) {
1102 renderContext_->DumpInfo();
1103 renderContext_->DumpAdvanceInfo();
1104 }
1105 }
1106
DumpViewDataPageNode(RefPtr<ViewDataWrap> viewDataWrap,bool needsRecordData)1107 void FrameNode::DumpViewDataPageNode(RefPtr<ViewDataWrap> viewDataWrap, bool needsRecordData)
1108 {
1109 if (pattern_) {
1110 pattern_->DumpViewDataPageNode(viewDataWrap, needsRecordData);
1111 }
1112 }
1113
CheckAutoSave()1114 bool FrameNode::CheckAutoSave()
1115 {
1116 if (pattern_) {
1117 return pattern_->CheckAutoSave();
1118 }
1119 return false;
1120 }
1121
MouseToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1122 void FrameNode::MouseToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1123 {
1124 std::string hoverEffect = "HoverEffect.Auto";
1125 /* no fixed attr below, just return */
1126 if (filter.IsFastFilter()) {
1127 return;
1128 }
1129 auto inputEventHub = GetOrCreateInputEventHub();
1130 if (inputEventHub) {
1131 hoverEffect = inputEventHub->GetHoverEffectStr();
1132 }
1133 json->PutExtAttr("hoverEffect", hoverEffect.c_str(), filter);
1134 }
1135
TouchToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1136 void FrameNode::TouchToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1137 {
1138 bool touchable = true;
1139 bool monopolizeEvents = false;
1140 std::string hitTestMode = "HitTestMode.Default";
1141 /* no fixed attr below, just return */
1142 if (filter.IsFastFilter()) {
1143 return;
1144 }
1145 auto gestureEventHub = GetOrCreateGestureEventHub();
1146 std::vector<DimensionRect> responseRegion;
1147 std::vector<DimensionRect> mouseResponseRegion;
1148 if (gestureEventHub) {
1149 touchable = gestureEventHub->GetTouchable();
1150 hitTestMode = gestureEventHub->GetHitTestModeStr();
1151 responseRegion = gestureEventHub->GetResponseRegion();
1152 mouseResponseRegion = gestureEventHub->GetMouseResponseRegion();
1153 monopolizeEvents = gestureEventHub->GetMonopolizeEvents();
1154 }
1155 json->PutExtAttr("touchable", touchable, filter);
1156 json->PutExtAttr("hitTestBehavior", hitTestMode.c_str(), filter);
1157 json->PutExtAttr("monopolizeEvents", monopolizeEvents, filter);
1158 auto jsArr = JsonUtil::CreateArray(true);
1159 for (int32_t i = 0; i < static_cast<int32_t>(responseRegion.size()); ++i) {
1160 auto iStr = std::to_string(i);
1161 jsArr->Put(iStr.c_str(), responseRegion[i].ToJsonString().c_str());
1162 }
1163 json->PutExtAttr("responseRegion", jsArr, filter);
1164 for (int32_t i = 0; i < static_cast<int32_t>(mouseResponseRegion.size()); ++i) {
1165 auto iStr = std::to_string(i);
1166 jsArr->Put(iStr.c_str(), mouseResponseRegion[i].ToJsonString().c_str());
1167 }
1168 json->PutExtAttr("mouseResponseRegion", jsArr, filter);
1169 }
1170
GeometryNodeToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1171 void FrameNode::GeometryNodeToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1172 {
1173 bool hasIdealWidth = false;
1174 bool hasIdealHeight = false;
1175 /* no fixed attr below, just return */
1176 if (filter.IsFastFilter()) {
1177 return;
1178 }
1179 if (layoutProperty_ && layoutProperty_->GetCalcLayoutConstraint()) {
1180 auto selfIdealSize = layoutProperty_->GetCalcLayoutConstraint()->selfIdealSize;
1181 hasIdealWidth = selfIdealSize.has_value() && selfIdealSize.value().Width().has_value();
1182 hasIdealHeight = selfIdealSize.has_value() && selfIdealSize.value().Height().has_value();
1183 }
1184
1185 auto jsonSize = json->GetValue("size");
1186 if (!hasIdealWidth) {
1187 auto idealWidthVpStr = std::to_string(Dimension(geometryNode_->GetFrameSize().Width()).ConvertToVp());
1188 auto widthStr = (idealWidthVpStr.substr(0, idealWidthVpStr.find(".") + SUBSTR_LENGTH) + DIMENSION_UNIT_VP);
1189 json->PutExtAttr("width", widthStr.c_str(), filter);
1190 if (jsonSize) {
1191 jsonSize->Put("width", widthStr.c_str());
1192 }
1193 }
1194
1195 if (!hasIdealHeight) {
1196 auto idealHeightVpStr = std::to_string(Dimension(geometryNode_->GetFrameSize().Height()).ConvertToVp());
1197 auto heightStr = (idealHeightVpStr.substr(0, idealHeightVpStr.find(".") + SUBSTR_LENGTH) + DIMENSION_UNIT_VP);
1198 json->PutExtAttr("height", heightStr.c_str(), filter);
1199 if (jsonSize) {
1200 jsonSize->Put("height", heightStr.c_str());
1201 }
1202 }
1203 }
1204
ToJsonValue(std::unique_ptr<JsonValue> & json,const InspectorFilter & filter) const1205 void FrameNode::ToJsonValue(std::unique_ptr<JsonValue>& json, const InspectorFilter& filter) const
1206 {
1207 if (renderContext_) {
1208 renderContext_->ToJsonValue(json, filter);
1209 }
1210 // scrollable in AccessibilityProperty
1211 ACE_PROPERTY_TO_JSON_VALUE(accessibilityProperty_, AccessibilityProperty);
1212 ACE_PROPERTY_TO_JSON_VALUE(layoutProperty_, LayoutProperty);
1213 ACE_PROPERTY_TO_JSON_VALUE(paintProperty_, PaintProperty);
1214 ACE_PROPERTY_TO_JSON_VALUE(pattern_, Pattern);
1215 if (eventHub_) {
1216 eventHub_->ToJsonValue(json, filter);
1217 }
1218 FocusHub::ToJsonValue(GetFocusHub(), json, filter);
1219 MouseToJsonValue(json, filter);
1220 TouchToJsonValue(json, filter);
1221 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_ELEVEN)) {
1222 #if defined(PREVIEW)
1223 GeometryNodeToJsonValue(json, filter);
1224 #endif
1225 } else {
1226 GeometryNodeToJsonValue(json, filter);
1227 }
1228 json->PutFixedAttr("id", propInspectorId_.value_or("").c_str(), filter, FIXED_ATTR_ID);
1229 }
1230
FromJson(const std::unique_ptr<JsonValue> & json)1231 void FrameNode::FromJson(const std::unique_ptr<JsonValue>& json)
1232 {
1233 if (renderContext_) {
1234 renderContext_->FromJson(json);
1235 }
1236 accessibilityProperty_->FromJson(json);
1237 layoutProperty_->FromJson(json);
1238 paintProperty_->FromJson(json);
1239 pattern_->FromJson(json);
1240 if (eventHub_) {
1241 eventHub_->FromJson(json);
1242 }
1243 }
1244
UpdateGeometryTransition()1245 void FrameNode::UpdateGeometryTransition()
1246 {
1247 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
1248 if (geometryTransition) {
1249 layoutProperty_->UpdateGeometryTransition("");
1250 layoutProperty_->UpdateGeometryTransition(geometryTransition->GetId());
1251 MarkDirtyNode();
1252 }
1253 auto children = GetChildren();
1254 for (const auto& child : children) {
1255 child->UpdateGeometryTransition();
1256 }
1257 }
1258
TriggerRsProfilerNodeMountCallbackIfExist()1259 void FrameNode::TriggerRsProfilerNodeMountCallbackIfExist()
1260 {
1261 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
1262 CHECK_NULL_VOID(renderContext_);
1263 auto callback = LayoutInspector::GetRsProfilerNodeMountCallback();
1264 if (callback) {
1265 FrameNodeInfo info { renderContext_->GetNodeId(), GetId(), GetTag(), GetDebugLine() };
1266 callback(info);
1267 }
1268 #endif
1269 }
1270
OnAttachToMainTree(bool recursive)1271 void FrameNode::OnAttachToMainTree(bool recursive)
1272 {
1273 TriggerRsProfilerNodeMountCallbackIfExist();
1274 eventHub_->FireOnAttach();
1275 eventHub_->FireOnAppear();
1276 renderContext_->OnNodeAppear(recursive);
1277 pattern_->OnAttachToMainTree();
1278
1279 if (isActive_ && SystemProperties::GetDeveloperModeOn()) {
1280 PaintDebugBoundary(SystemProperties::GetDebugBoundaryEnabled());
1281 }
1282 bool forceMeasure = !GetPattern()->ReusedNodeSkipMeasure();
1283 // node may have been measured before AttachToMainTree
1284 if (geometryNode_->GetParentLayoutConstraint().has_value() && !UseOffscreenProcess() && forceMeasure) {
1285 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE_SELF);
1286 }
1287 UINode::OnAttachToMainTree(recursive);
1288 auto context = GetContext();
1289 CHECK_NULL_VOID(context);
1290 auto predictLayoutNode = std::move(predictLayoutNode_);
1291 for (auto& node : predictLayoutNode) {
1292 auto frameNode = node.Upgrade();
1293 if (frameNode && frameNode->isLayoutDirtyMarked_) {
1294 context->AddDirtyLayoutNode(frameNode);
1295 }
1296 }
1297
1298 if (isPropertyDiffMarked_) {
1299 context->AddDirtyPropertyNode(Claim(this));
1300 }
1301 if (!hasPendingRequest_) {
1302 return;
1303 }
1304 context->RequestFrame();
1305 hasPendingRequest_ = false;
1306 }
1307
OnAttachToBuilderNode(NodeStatus nodeStatus)1308 void FrameNode::OnAttachToBuilderNode(NodeStatus nodeStatus)
1309 {
1310 pattern_->OnAttachToBuilderNode(nodeStatus);
1311 }
1312
RenderCustomChild(int64_t deadline)1313 bool FrameNode::RenderCustomChild(int64_t deadline)
1314 {
1315 if (!pattern_->RenderCustomChild(deadline)) {
1316 return false;
1317 }
1318 return UINode::RenderCustomChild(deadline);
1319 }
1320
OnConfigurationUpdate(const ConfigurationChange & configurationChange)1321 void FrameNode::OnConfigurationUpdate(const ConfigurationChange& configurationChange)
1322 {
1323 if (configurationChange.languageUpdate) {
1324 pattern_->OnLanguageConfigurationUpdate();
1325 MarkModifyDone();
1326 MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1327 }
1328 if (configurationChange.colorModeUpdate) {
1329 pattern_->OnColorConfigurationUpdate();
1330 if (colorModeUpdateCallback_) {
1331 // copy it first in case of changing colorModeUpdateCallback_ in the callback
1332 auto cb = colorModeUpdateCallback_;
1333 cb();
1334 }
1335 MarkModifyDone();
1336 MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1337 }
1338 if (configurationChange.directionUpdate) {
1339 pattern_->OnDirectionConfigurationUpdate();
1340 MarkModifyDone();
1341 MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1342 }
1343 if (configurationChange.dpiUpdate) {
1344 pattern_->OnDpiConfigurationUpdate();
1345 MarkModifyDone();
1346 MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1347 }
1348 if (configurationChange.fontUpdate) {
1349 pattern_->OnFontConfigurationUpdate();
1350 MarkModifyDone();
1351 MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1352 }
1353 if (configurationChange.iconUpdate) {
1354 pattern_->OnIconConfigurationUpdate();
1355 MarkModifyDone();
1356 MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1357 }
1358 if (configurationChange.skinUpdate) {
1359 MarkModifyDone();
1360 MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1361 }
1362 if (configurationChange.fontScaleUpdate) {
1363 pattern_->OnFontScaleConfigurationUpdate();
1364 MarkModifyDone();
1365 MarkDirtyNode(PROPERTY_UPDATE_MEASURE);
1366 }
1367 NotifyConfigurationChangeNdk(configurationChange);
1368 }
1369
NotifyConfigurationChangeNdk(const ConfigurationChange & configurationChange)1370 void FrameNode::NotifyConfigurationChangeNdk(const ConfigurationChange& configurationChange)
1371 {
1372 if (ndkColorModeUpdateCallback_ && configurationChange.colorModeUpdate &&
1373 colorMode_ != SystemProperties::GetColorMode()) {
1374 auto colorModeChange = ndkColorModeUpdateCallback_;
1375 colorModeChange(SystemProperties::GetColorMode() == ColorMode::DARK);
1376 colorMode_ = SystemProperties::GetColorMode();
1377 }
1378
1379 if (ndkFontUpdateCallback_ && (configurationChange.fontScaleUpdate || configurationChange.fontWeightScaleUpdate)) {
1380 auto fontChangeCallback = ndkFontUpdateCallback_;
1381 auto pipeline = GetContextWithCheck();
1382 CHECK_NULL_VOID(pipeline);
1383 fontChangeCallback(pipeline->GetFontScale(), pipeline->GetFontWeightScale());
1384 }
1385 }
1386
NotifyVisibleChange(VisibleType preVisibility,VisibleType currentVisibility)1387 void FrameNode::NotifyVisibleChange(VisibleType preVisibility, VisibleType currentVisibility)
1388 {
1389 if ((preVisibility != currentVisibility &&
1390 (preVisibility == VisibleType::GONE || currentVisibility == VisibleType::GONE)) &&
1391 SelfExpansive()) {
1392 MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
1393 }
1394 pattern_->OnVisibleChange(currentVisibility == VisibleType::VISIBLE);
1395 UpdateChildrenVisible(preVisibility, currentVisibility);
1396 }
1397
TryVisibleChangeOnDescendant(VisibleType preVisibility,VisibleType currentVisibility)1398 void FrameNode::TryVisibleChangeOnDescendant(VisibleType preVisibility, VisibleType currentVisibility)
1399 {
1400 auto layoutProperty = GetLayoutProperty();
1401 if (layoutProperty && layoutProperty->GetVisibilityValue(VisibleType::VISIBLE) != VisibleType::VISIBLE) {
1402 return;
1403 }
1404 NotifyVisibleChange(preVisibility, currentVisibility);
1405 }
1406
OnDetachFromMainTree(bool recursive,PipelineContext * context)1407 void FrameNode::OnDetachFromMainTree(bool recursive, PipelineContext* context)
1408 {
1409 auto focusHub = GetFocusHub();
1410 if (focusHub) {
1411 auto focusView = focusHub->GetFirstChildFocusView();
1412 if (focusView) {
1413 focusView->FocusViewClose(true);
1414 }
1415 focusHub->RemoveSelf();
1416 }
1417 eventHub_->FireOnDetach();
1418 pattern_->OnDetachFromMainTree();
1419 eventHub_->FireOnDisappear();
1420 CHECK_NULL_VOID(renderContext_);
1421 renderContext_->OnNodeDisappear(recursive);
1422 if (context) {
1423 const auto& safeAreaManager = context->GetSafeAreaManager();
1424 if (safeAreaManager) {
1425 safeAreaManager->RemoveRestoreNode(WeakClaim(this));
1426 }
1427 }
1428 }
1429
SwapDirtyLayoutWrapperOnMainThread(const RefPtr<LayoutWrapper> & dirty)1430 void FrameNode::SwapDirtyLayoutWrapperOnMainThread(const RefPtr<LayoutWrapper>& dirty)
1431 {
1432 CHECK_NULL_VOID(dirty);
1433
1434 // update new layout constrain.
1435 layoutProperty_->UpdateLayoutConstraint(dirty->GetLayoutProperty());
1436
1437 // active change flag judge.
1438 SetActive(dirty->IsActive());
1439 if (!isActive_) {
1440 return;
1441 }
1442
1443 // update layout size.
1444 bool frameSizeChange = geometryNode_->GetFrameSize() != dirty->GetGeometryNode()->GetFrameSize();
1445 bool frameOffsetChange = geometryNode_->GetFrameOffset() != dirty->GetGeometryNode()->GetFrameOffset();
1446 bool contentSizeChange = geometryNode_->GetContentSize() != dirty->GetGeometryNode()->GetContentSize();
1447 bool contentOffsetChange = geometryNode_->GetContentOffset() != dirty->GetGeometryNode()->GetContentOffset();
1448
1449 SetGeometryNode(dirty->GetGeometryNode());
1450
1451 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
1452 if (geometryTransition != nullptr && geometryTransition->IsRunning(WeakClaim(this))) {
1453 geometryTransition->DidLayout(dirty);
1454 if (geometryTransition->IsNodeOutAndActive(WeakClaim(this))) {
1455 isLayoutDirtyMarked_ = true;
1456 }
1457 } else if (frameSizeChange || frameOffsetChange || HasPositionProp() ||
1458 (pattern_->GetContextParam().has_value() && contentSizeChange)) {
1459 renderContext_->SyncGeometryProperties(RawPtr(dirty->GetGeometryNode()));
1460 }
1461
1462 // clean layout flag.
1463 layoutProperty_->CleanDirty();
1464 DirtySwapConfig config { frameSizeChange, frameOffsetChange, contentSizeChange, contentOffsetChange };
1465 // check if need to paint content.
1466 auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(dirty->GetLayoutAlgorithm());
1467 CHECK_NULL_VOID(layoutAlgorithmWrapper);
1468 config.skipMeasure = layoutAlgorithmWrapper->SkipMeasure() || dirty->SkipMeasureContent();
1469 config.skipLayout = layoutAlgorithmWrapper->SkipLayout();
1470 if ((config.skipMeasure == false) && (config.skipLayout == false)) {
1471 auto pipeline = GetContext();
1472 CHECK_NULL_VOID(pipeline);
1473 if (eventHub_ != nullptr) {
1474 eventHub_->FireLayoutNDKCallback(Claim(pipeline));
1475 }
1476 if (GetInspectorId().has_value()) {
1477 pipeline->OnLayoutCompleted(GetInspectorId()->c_str());
1478 }
1479 }
1480 auto needRerender = pattern_->OnDirtyLayoutWrapperSwap(dirty, config);
1481 needRerender = needRerender || pattern_->OnDirtyLayoutWrapperSwap(dirty, config.skipMeasure, config.skipLayout);
1482 if (needRerender || CheckNeedRender(paintProperty_->GetPropertyChangeFlag())) {
1483 MarkDirtyNode(true, true, PROPERTY_UPDATE_RENDER);
1484 }
1485
1486 // update border.
1487 if (layoutProperty_->GetBorderWidthProperty()) {
1488 if (!renderContext_->HasBorderColor()) {
1489 BorderColorProperty borderColorProperty;
1490 borderColorProperty.SetColor(Color::BLACK);
1491 renderContext_->UpdateBorderColor(borderColorProperty);
1492 }
1493 if (!renderContext_->HasBorderStyle()) {
1494 BorderStyleProperty borderStyleProperty;
1495 borderStyleProperty.SetBorderStyle(BorderStyle::SOLID);
1496 renderContext_->UpdateBorderStyle(borderStyleProperty);
1497 }
1498 if (!renderContext_->HasDashGap()) {
1499 BorderWidthProperty dashGapProperty;
1500 dashGapProperty.SetBorderWidth(Dimension(-1));
1501 renderContext_->UpdateDashGap(dashGapProperty);
1502 }
1503 if (!renderContext_->HasDashWidth()) {
1504 BorderWidthProperty dashWidthProperty;
1505 dashWidthProperty.SetBorderWidth(Dimension(-1));
1506 renderContext_->UpdateDashWidth(dashWidthProperty);
1507 }
1508 if (layoutProperty_->GetLayoutConstraint().has_value()) {
1509 renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
1510 ScaleProperty::CreateScaleProperty(),
1511 layoutProperty_->GetLayoutConstraint()->percentReference.Width()));
1512 } else {
1513 renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
1514 ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth()));
1515 }
1516 }
1517
1518 // update background
1519 if (builderFunc_) {
1520 auto builderNode = builderFunc_();
1521 auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
1522 AceType::MakeRefPtr<LinearLayoutPattern>(true));
1523 if (builderNode) {
1524 builderNode->MountToParent(columnNode);
1525 }
1526 SetBackgroundLayoutConstraint(columnNode);
1527 renderContext_->CreateBackgroundPixelMap(columnNode);
1528 builderFunc_ = nullptr;
1529 backgroundNode_ = columnNode;
1530 }
1531 UpdateFocusState();
1532
1533 // rebuild child render node.
1534 RebuildRenderContextTree();
1535 }
1536
SetBackgroundLayoutConstraint(const RefPtr<FrameNode> & customNode)1537 void FrameNode::SetBackgroundLayoutConstraint(const RefPtr<FrameNode>& customNode)
1538 {
1539 CHECK_NULL_VOID(customNode);
1540 LayoutConstraintF layoutConstraint;
1541 layoutConstraint.scaleProperty = ScaleProperty::CreateScaleProperty();
1542 layoutConstraint.percentReference.SetWidth(geometryNode_->GetFrameSize().Width());
1543 layoutConstraint.percentReference.SetHeight(geometryNode_->GetFrameSize().Height());
1544 layoutConstraint.maxSize.SetWidth(geometryNode_->GetFrameSize().Width());
1545 layoutConstraint.maxSize.SetHeight(geometryNode_->GetFrameSize().Height());
1546 customNode->GetGeometryNode()->SetParentLayoutConstraint(layoutConstraint);
1547 }
1548
AdjustGridOffset()1549 void FrameNode::AdjustGridOffset()
1550 {
1551 if (!isActive_) {
1552 return;
1553 }
1554 if (layoutProperty_->UpdateGridOffset(Claim(this))) {
1555 renderContext_->UpdateOffset(OffsetT<Dimension>());
1556 renderContext_->UpdateAnchor(OffsetT<Dimension>());
1557 renderContext_->SyncGeometryProperties(RawPtr(GetGeometryNode()));
1558 }
1559 }
1560
ClearUserOnAreaChange()1561 void FrameNode::ClearUserOnAreaChange()
1562 {
1563 if (eventHub_) {
1564 eventHub_->ClearUserOnAreaChanged();
1565 }
1566 }
1567
SetOnAreaChangeCallback(OnAreaChangedFunc && callback)1568 void FrameNode::SetOnAreaChangeCallback(OnAreaChangedFunc&& callback)
1569 {
1570 InitLastArea();
1571 eventHub_->SetOnAreaChanged(std::move(callback));
1572 }
1573
TriggerOnAreaChangeCallback(uint64_t nanoTimestamp)1574 void FrameNode::TriggerOnAreaChangeCallback(uint64_t nanoTimestamp)
1575 {
1576 if (!IsActive()) {
1577 return;
1578 }
1579 if ((eventHub_->HasOnAreaChanged() || eventHub_->HasInnerOnAreaChanged()) && lastFrameRect_ &&
1580 lastParentOffsetToWindow_) {
1581 auto currFrameRect = geometryNode_->GetFrameRect();
1582 if (renderContext_ && renderContext_->GetPositionProperty()) {
1583 if (renderContext_->GetPositionProperty()->HasPosition()) {
1584 auto renderPosition = ContextPositionConvertToPX(
1585 renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
1586 currFrameRect.SetOffset(
1587 { static_cast<float>(renderPosition.first), static_cast<float>(renderPosition.second) });
1588 }
1589 }
1590 auto currParentOffsetToWindow = CalculateOffsetRelativeToWindow(nanoTimestamp) - currFrameRect.GetOffset();
1591 if (currFrameRect != *lastFrameRect_ || currParentOffsetToWindow != *lastParentOffsetToWindow_) {
1592 if (eventHub_->HasInnerOnAreaChanged()) {
1593 eventHub_->FireInnerOnAreaChanged(
1594 *lastFrameRect_, *lastParentOffsetToWindow_, currFrameRect, currParentOffsetToWindow);
1595 }
1596 if (eventHub_->HasOnAreaChanged()) {
1597 eventHub_->FireOnAreaChanged(*lastFrameRect_, *lastParentOffsetToWindow_,
1598 GetFrameRectWithSafeArea(true), GetParentGlobalOffsetWithSafeArea(true, true));
1599 }
1600 *lastFrameRect_ = currFrameRect;
1601 *lastParentOffsetToWindow_ = currParentOffsetToWindow;
1602 }
1603 }
1604 pattern_->OnAreaChangedInner();
1605 }
1606
SetOnSizeChangeCallback(OnSizeChangedFunc && callback)1607 void FrameNode::SetOnSizeChangeCallback(OnSizeChangedFunc&& callback)
1608 {
1609 if (!lastFrameNodeRect_) {
1610 lastFrameNodeRect_ = std::make_unique<RectF>();
1611 }
1612 eventHub_->SetOnSizeChanged(std::move(callback));
1613 }
1614
AddInnerOnSizeChangeCallback(int32_t id,OnSizeChangedFunc && callback)1615 void FrameNode::AddInnerOnSizeChangeCallback(int32_t id, OnSizeChangedFunc&& callback)
1616 {
1617 if (!lastFrameNodeRect_) {
1618 lastFrameNodeRect_ = std::make_unique<RectF>();
1619 }
1620 eventHub_->AddInnerOnSizeChanged(id, std::move(callback));
1621 }
1622
SetJSFrameNodeOnSizeChangeCallback(OnSizeChangedFunc && callback)1623 void FrameNode::SetJSFrameNodeOnSizeChangeCallback(OnSizeChangedFunc&& callback)
1624 {
1625 if (!lastFrameNodeRect_) {
1626 lastFrameNodeRect_ = std::make_unique<RectF>();
1627 }
1628 eventHub_->SetJSFrameNodeOnSizeChangeCallback(std::move(callback));
1629 }
1630
GetRectWithFrame()1631 RectF FrameNode::GetRectWithFrame()
1632 {
1633 auto currFrameRect = geometryNode_->GetFrameRect();
1634 if (renderContext_ && renderContext_->GetPositionProperty()) {
1635 if (renderContext_->GetPositionProperty()->HasPosition()) {
1636 auto renderPosition = ContextPositionConvertToPX(
1637 renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
1638 currFrameRect.SetOffset(
1639 { static_cast<float>(renderPosition.first), static_cast<float>(renderPosition.second) });
1640 }
1641 }
1642 return currFrameRect;
1643 }
1644
GetRectWithRender()1645 RectF FrameNode::GetRectWithRender()
1646 {
1647 RectF currFrameRect;
1648 if (renderContext_) {
1649 currFrameRect = renderContext_->GetPaintRectWithoutTransform();
1650 }
1651 if (renderContext_ && renderContext_->GetPositionProperty()) {
1652 if (renderContext_->GetPositionProperty()->HasPosition()) {
1653 auto renderPosition =
1654 ContextPositionConvertToPX(renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
1655 currFrameRect.SetOffset(
1656 { static_cast<float>(renderPosition.first), static_cast<float>(renderPosition.second) });
1657 }
1658 }
1659 return currFrameRect;
1660 }
1661
CheckAncestorPageShow()1662 bool FrameNode::CheckAncestorPageShow()
1663 {
1664 auto pageNode = GetPageNode();
1665 if (!pageNode) {
1666 return true;
1667 }
1668 return pageNode->GetPattern<PagePattern>()->IsOnShow();
1669 }
1670
TriggerOnSizeChangeCallback()1671 void FrameNode::TriggerOnSizeChangeCallback()
1672 {
1673 if (!IsActive() || !CheckAncestorPageShow()) {
1674 return;
1675 }
1676 if ((eventHub_->HasOnSizeChanged() || eventHub_->HasInnerOnSizeChanged()) && lastFrameNodeRect_) {
1677 auto currFrameRect = GetRectWithRender();
1678 if (currFrameRect.GetSize() != (*lastFrameNodeRect_).GetSize()) {
1679 onSizeChangeDumpInfo dumpInfo { GetCurrentTimestamp(), *lastFrameNodeRect_, currFrameRect };
1680 if (onSizeChangeDumpInfos.size() >= SIZE_CHANGE_DUMP_SIZE) {
1681 onSizeChangeDumpInfos.erase(onSizeChangeDumpInfos.begin());
1682 }
1683 onSizeChangeDumpInfos.emplace_back(dumpInfo);
1684 if (eventHub_->HasOnSizeChanged()) {
1685 eventHub_->FireOnSizeChanged(*lastFrameNodeRect_, currFrameRect);
1686 }
1687 if (eventHub_->HasInnerOnSizeChanged()) {
1688 eventHub_->FireInnerOnSizeChanged(*lastFrameNodeRect_, currFrameRect);
1689 }
1690 eventHub_->FireJSFrameNodeOnSizeChanged(*lastFrameNodeRect_, currFrameRect);
1691 *lastFrameNodeRect_ = currFrameRect;
1692 }
1693 }
1694 }
1695
IsFrameDisappear() const1696 bool FrameNode::IsFrameDisappear() const
1697 {
1698 auto context = GetContext();
1699 CHECK_NULL_RETURN(context, true);
1700 bool isFrameDisappear = !context->GetOnShow() || !IsOnMainTree() || !IsVisible();
1701 if (isFrameDisappear) {
1702 return true;
1703 }
1704 bool curFrameIsActive = isActive_;
1705 bool curIsVisible = IsVisible();
1706 auto parent = GetParent();
1707 while (parent) {
1708 auto parentFrame = AceType::DynamicCast<FrameNode>(parent);
1709 if (!parentFrame) {
1710 parent = parent->GetParent();
1711 continue;
1712 }
1713 if (!parentFrame->isActive_) {
1714 curFrameIsActive = false;
1715 break;
1716 }
1717 if (!parentFrame->IsVisible()) {
1718 curIsVisible = false;
1719 break;
1720 }
1721 parent = parent->GetParent();
1722 }
1723 return !curIsVisible || !curFrameIsActive;
1724 }
1725
IsFrameDisappear(uint64_t timestamp)1726 bool FrameNode::IsFrameDisappear(uint64_t timestamp)
1727 {
1728 auto context = GetContext();
1729 CHECK_NULL_RETURN(context, true);
1730 auto isOnShow = context->GetOnShow();
1731 auto isOnMainTree = AllowVisibleAreaCheck();
1732 auto isSelfVisible = IsVisible();
1733 if (!isSelfVisible) {
1734 SetVisibleAreaChangeTriggerReason(VisibleAreaChangeTriggerReason::SELF_INVISIBLE);
1735 }
1736 if (!isOnMainTree) {
1737 SetVisibleAreaChangeTriggerReason(VisibleAreaChangeTriggerReason::IS_NOT_ON_MAINTREE);
1738 }
1739 if (!isOnShow) {
1740 SetVisibleAreaChangeTriggerReason(VisibleAreaChangeTriggerReason::BACKGROUND);
1741 }
1742 bool isFrameDisappear = !isOnShow || !isOnMainTree || !isSelfVisible;
1743 if (isFrameDisappear) {
1744 cachedIsFrameDisappear_ = { timestamp, true };
1745 return true;
1746 }
1747 auto result = IsFrameAncestorDisappear(timestamp);
1748 if (result) {
1749 SetVisibleAreaChangeTriggerReason(VisibleAreaChangeTriggerReason::ANCESTOR_INVISIBLE);
1750 }
1751 return result;
1752 }
1753
IsFrameAncestorDisappear(uint64_t timestamp)1754 bool FrameNode::IsFrameAncestorDisappear(uint64_t timestamp)
1755 {
1756 bool curFrameIsActive = isActive_;
1757 bool curIsVisible = IsVisible();
1758 bool result = !curIsVisible || !curFrameIsActive;
1759 RefPtr<FrameNode> parentUi = GetAncestorNodeOfFrame(false);
1760 if (!parentUi) {
1761 cachedIsFrameDisappear_ = { timestamp, result };
1762 return result;
1763 }
1764
1765 auto parentIsFrameDisappear = parentUi->cachedIsFrameDisappear_;
1766 if (parentIsFrameDisappear.first == timestamp) {
1767 result = result || parentIsFrameDisappear.second;
1768 cachedIsFrameDisappear_ = { timestamp, result };
1769 return result;
1770 }
1771 result = result || (parentUi->IsFrameAncestorDisappear(timestamp));
1772 cachedIsFrameDisappear_ = { timestamp, result };
1773 return result;
1774 }
1775
TriggerVisibleAreaChangeCallback(uint64_t timestamp,bool forceDisappear)1776 void FrameNode::TriggerVisibleAreaChangeCallback(uint64_t timestamp, bool forceDisappear)
1777 {
1778 auto context = GetContext();
1779 CHECK_NULL_VOID(context);
1780 CHECK_NULL_VOID(eventHub_);
1781
1782 ProcessThrottledVisibleCallback();
1783 auto hasInnerCallback = eventHub_->HasVisibleAreaCallback(false);
1784 auto hasUserCallback = eventHub_->HasVisibleAreaCallback(true);
1785 if (!hasInnerCallback && !hasUserCallback) {
1786 return;
1787 }
1788
1789 auto& visibleAreaUserRatios = eventHub_->GetVisibleAreaRatios(true);
1790 auto& visibleAreaUserCallback = eventHub_->GetVisibleAreaCallback(true);
1791 auto& visibleAreaInnerRatios = eventHub_->GetVisibleAreaRatios(false);
1792 auto& visibleAreaInnerCallback = eventHub_->GetVisibleAreaCallback(false);
1793
1794 if (forceDisappear || IsFrameDisappear(timestamp)) {
1795 if (!NearEqual(lastInnerVisibleRatio_, VISIBLE_RATIO_MIN)) {
1796 ProcessAllVisibleCallback(visibleAreaInnerRatios, visibleAreaInnerCallback, VISIBLE_RATIO_MIN,
1797 lastInnerVisibleCallbackRatio_, false, true);
1798 lastInnerVisibleRatio_ = VISIBLE_RATIO_MIN;
1799 }
1800 if (!NearEqual(lastVisibleRatio_, VISIBLE_RATIO_MIN)) {
1801 ProcessAllVisibleCallback(
1802 visibleAreaUserRatios, visibleAreaUserCallback, VISIBLE_RATIO_MIN, lastVisibleCallbackRatio_);
1803 lastVisibleRatio_ = VISIBLE_RATIO_MIN;
1804 }
1805 return;
1806 }
1807
1808 SetVisibleAreaChangeTriggerReason(VisibleAreaChangeTriggerReason::VISIBLE_AREA_CHANGE);
1809 if (hasInnerCallback) {
1810 auto visibleResult = GetCacheVisibleRect(timestamp);
1811 if (isCalculateInnerVisibleRectClip_) {
1812 ProcessVisibleAreaChangeEvent(visibleResult.innerVisibleRect, visibleResult.frameRect,
1813 visibleAreaInnerRatios, visibleAreaInnerCallback, false);
1814 } else {
1815 ProcessVisibleAreaChangeEvent(visibleResult.visibleRect, visibleResult.frameRect,
1816 visibleAreaInnerRatios, visibleAreaInnerCallback, false);
1817 }
1818 if (hasUserCallback) {
1819 ProcessVisibleAreaChangeEvent(visibleResult.visibleRect, visibleResult.frameRect,
1820 visibleAreaUserRatios, visibleAreaUserCallback, true);
1821 }
1822 } else {
1823 auto visibleResult = GetCacheVisibleRect(timestamp);
1824 ProcessVisibleAreaChangeEvent(visibleResult.visibleRect, visibleResult.frameRect,
1825 visibleAreaUserRatios, visibleAreaUserCallback, true);
1826 }
1827 }
1828
ProcessVisibleAreaChangeEvent(const RectF & visibleRect,const RectF & frameRect,const std::vector<double> & visibleAreaRatios,VisibleCallbackInfo & visibleAreaCallback,bool isUser)1829 void FrameNode::ProcessVisibleAreaChangeEvent(const RectF& visibleRect, const RectF& frameRect,
1830 const std::vector<double>& visibleAreaRatios, VisibleCallbackInfo& visibleAreaCallback, bool isUser)
1831 {
1832 double currentVisibleRatio =
1833 std::clamp(CalculateCurrentVisibleRatio(visibleRect, frameRect), VISIBLE_RATIO_MIN, VISIBLE_RATIO_MAX);
1834 if (isUser) {
1835 if (!NearEqual(currentVisibleRatio, lastVisibleRatio_)) {
1836 auto lastVisibleCallbackRatio = lastVisibleCallbackRatio_;
1837 ProcessAllVisibleCallback(
1838 visibleAreaRatios, visibleAreaCallback, currentVisibleRatio, lastVisibleCallbackRatio);
1839 lastVisibleRatio_ = currentVisibleRatio;
1840 }
1841 } else {
1842 if (!NearEqual(currentVisibleRatio, lastInnerVisibleRatio_)) {
1843 auto lastVisibleCallbackRatio = lastInnerVisibleCallbackRatio_;
1844 ProcessAllVisibleCallback(visibleAreaRatios, visibleAreaCallback, currentVisibleRatio,
1845 lastVisibleCallbackRatio, false, true);
1846 lastInnerVisibleRatio_ = currentVisibleRatio;
1847 }
1848 }
1849 }
1850
CalculateCurrentVisibleRatio(const RectF & visibleRect,const RectF & renderRect)1851 double FrameNode::CalculateCurrentVisibleRatio(const RectF& visibleRect, const RectF& renderRect)
1852 {
1853 if (visibleRect.IsEmpty() || renderRect.IsEmpty()) {
1854 return 0.0;
1855 }
1856 return visibleRect.Width() * visibleRect.Height() / (renderRect.Width() * renderRect.Height());
1857 }
1858
ProcessAllVisibleCallback(const std::vector<double> & visibleAreaUserRatios,VisibleCallbackInfo & visibleAreaUserCallback,double currentVisibleRatio,double lastVisibleRatio,bool isThrottled,bool isInner)1859 void FrameNode::ProcessAllVisibleCallback(const std::vector<double>& visibleAreaUserRatios,
1860 VisibleCallbackInfo& visibleAreaUserCallback, double currentVisibleRatio, double lastVisibleRatio,
1861 bool isThrottled, bool isInner)
1862 {
1863 bool isHandled = false;
1864 bool isVisible = false;
1865 double* lastVisibleCallbackRatio = isThrottled ? &lastThrottledVisibleCbRatio_ :
1866 (isInner ? &lastInnerVisibleCallbackRatio_ : &lastVisibleCallbackRatio_);
1867
1868 for (const auto& callbackRatio : visibleAreaUserRatios) {
1869 if (GreatNotEqual(currentVisibleRatio, callbackRatio) && LessOrEqual(lastVisibleRatio, callbackRatio)) {
1870 *lastVisibleCallbackRatio = currentVisibleRatio;
1871 isVisible = true;
1872 isHandled = true;
1873 } else if (LessNotEqual(currentVisibleRatio, callbackRatio) && GreatOrEqual(lastVisibleRatio, callbackRatio)) {
1874 *lastVisibleCallbackRatio = currentVisibleRatio;
1875 isVisible = false;
1876 isHandled = true;
1877 } else if (NearEqual(callbackRatio, VISIBLE_RATIO_MIN) && NearEqual(currentVisibleRatio, callbackRatio)) {
1878 *lastVisibleCallbackRatio = VISIBLE_RATIO_MIN;
1879 currentVisibleRatio = VISIBLE_RATIO_MIN;
1880 isVisible = false;
1881 isHandled = true;
1882 } else if (NearEqual(callbackRatio, VISIBLE_RATIO_MAX) && NearEqual(currentVisibleRatio, callbackRatio)) {
1883 *lastVisibleCallbackRatio = VISIBLE_RATIO_MAX;
1884 currentVisibleRatio = VISIBLE_RATIO_MAX;
1885 isVisible = true;
1886 isHandled = true;
1887 }
1888 }
1889
1890 auto callback = visibleAreaUserCallback.callback;
1891 if (isHandled && callback) {
1892 if (GetTag() == V2::WEB_ETS_TAG) {
1893 TAG_LOGI(AceLogTag::ACE_UIEVENT, "exp=%{public}d ratio=%{public}s %{public}d-%{public}s reason=%{public}d",
1894 isVisible, std::to_string(currentVisibleRatio).c_str(), GetId(),
1895 std::to_string(GetAccessibilityId()).c_str(), static_cast<int32_t>(visibleAreaChangeTriggerReason_));
1896 }
1897 callback(isVisible, currentVisibleRatio);
1898 }
1899 }
1900
ThrottledVisibleTask()1901 void FrameNode::ThrottledVisibleTask()
1902 {
1903 CHECK_NULL_VOID(eventHub_);
1904 auto& userRatios = eventHub_->GetThrottledVisibleAreaRatios();
1905 auto& userCallback = eventHub_->GetThrottledVisibleAreaCallback();
1906 CHECK_NULL_VOID(userCallback.callback);
1907 if (!throttledCallbackOnTheWay_) {
1908 return;
1909 }
1910
1911 auto pipeline = GetContext();
1912 CHECK_NULL_VOID(pipeline);
1913 auto visibleAreaRealTime = pipeline->GetVisibleAreaRealTime();
1914 auto visibleResult = GetCacheVisibleRect(pipeline->GetVsyncTime());
1915 RectF frameRect = visibleResult.frameRect;
1916 RectF visibleRect = visibleResult.visibleRect;
1917 double ratio = IsFrameDisappear() ? VISIBLE_RATIO_MIN
1918 : std::clamp(CalculateCurrentVisibleRatio(visibleRect, frameRect),
1919 VISIBLE_RATIO_MIN, VISIBLE_RATIO_MAX);
1920 if (visibleAreaRealTime) {
1921 if (NearEqual(ratio, lastThrottledVisibleRatio_)) {
1922 throttledCallbackOnTheWay_ = false;
1923 return;
1924 }
1925 ProcessAllVisibleCallback(userRatios, userCallback, ratio, lastThrottledVisibleCbRatio_, true);
1926 lastThrottledVisibleRatio_ = ratio;
1927 throttledCallbackOnTheWay_ = false;
1928 lastThrottledTriggerTime_ = GetCurrentTimestamp();
1929 } else {
1930 if (!NearEqual(ratio, lastThrottledVisibleRatio_)) {
1931 ProcessAllVisibleCallback(userRatios, userCallback, ratio, lastThrottledVisibleCbRatio_, true);
1932 lastThrottledVisibleRatio_ = ratio;
1933 }
1934 throttledCallbackOnTheWay_ = false;
1935 lastThrottledTriggerTime_ = GetCurrentTimestamp();
1936 }
1937 }
1938
ProcessThrottledVisibleCallback()1939 void FrameNode::ProcessThrottledVisibleCallback()
1940 {
1941 CHECK_NULL_VOID(eventHub_);
1942 auto& visibleAreaUserCallback = eventHub_->GetThrottledVisibleAreaCallback();
1943 CHECK_NULL_VOID(visibleAreaUserCallback.callback);
1944
1945 auto task = [weak = WeakClaim(this)]() {
1946 auto node = weak.Upgrade();
1947 CHECK_NULL_VOID(node);
1948 node->ThrottledVisibleTask();
1949 };
1950
1951 auto pipeline = GetContextRefPtr();
1952 CHECK_NULL_VOID(pipeline);
1953 auto executor = pipeline->GetTaskExecutor();
1954 CHECK_NULL_VOID(executor);
1955
1956 if (throttledCallbackOnTheWay_) {
1957 return;
1958 }
1959
1960 throttledCallbackOnTheWay_ = true;
1961 int64_t interval = GetCurrentTimestamp() - lastThrottledTriggerTime_;
1962 if (interval < visibleAreaUserCallback.period) {
1963 executor->PostDelayedTask(std::move(task), TaskExecutor::TaskType::UI, visibleAreaUserCallback.period,
1964 "ThrottledVisibleChangeCallback", PriorityType::IDLE);
1965 } else {
1966 executor->PostTask(
1967 std::move(task), TaskExecutor::TaskType::UI, "ThrottledVisibleChangeCallback", PriorityType::IDLE);
1968 }
1969 }
1970
SetActive(bool active,bool needRebuildRenderContext)1971 void FrameNode::SetActive(bool active, bool needRebuildRenderContext)
1972 {
1973 bool activeChanged = false;
1974 if (active && !isActive_) {
1975 pattern_->OnActive();
1976 isActive_ = true;
1977 activeChanged = true;
1978 }
1979 if (!active && isActive_) {
1980 pattern_->OnInActive();
1981 isActive_ = false;
1982 activeChanged = true;
1983 }
1984 CHECK_NULL_VOID(activeChanged);
1985 auto parent = GetAncestorNodeOfFrame(false);
1986 if (parent) {
1987 parent->MarkNeedSyncRenderTree();
1988 if (needRebuildRenderContext) {
1989 auto pipeline = GetContext();
1990 CHECK_NULL_VOID(pipeline);
1991 auto task = [weak = AceType::WeakClaim(AceType::RawPtr(parent))]() {
1992 auto parent = weak.Upgrade();
1993 CHECK_NULL_VOID(parent);
1994 parent->RebuildRenderContextTree();
1995 };
1996 pipeline->AddAfterLayoutTask(task);
1997 }
1998 }
1999 if (isActive_ && SystemProperties::GetDeveloperModeOn()) {
2000 PaintDebugBoundary(SystemProperties::GetDebugBoundaryEnabled());
2001 }
2002 }
2003
SetGeometryNode(const RefPtr<GeometryNode> & node)2004 void FrameNode::SetGeometryNode(const RefPtr<GeometryNode>& node)
2005 {
2006 geometryNode_ = node;
2007 }
2008
CreateLayoutTask(bool forceUseMainThread)2009 void FrameNode::CreateLayoutTask(bool forceUseMainThread)
2010 {
2011 if (!isLayoutDirtyMarked_) {
2012 return;
2013 }
2014 SetRootMeasureNode(true);
2015 UpdateLayoutPropertyFlag();
2016 SetSkipSyncGeometryNode(false);
2017 if (layoutProperty_->GetLayoutRect()) {
2018 SetActive(true, true);
2019 Measure(std::nullopt);
2020 Layout();
2021 } else {
2022 {
2023 auto layoutConstraint = GetLayoutConstraint();
2024 ACE_SCOPED_TRACE("CreateTaskMeasure[%s][self:%d][parent:%d][layoutConstraint:%s]", GetTag().c_str(),
2025 GetId(), GetAncestorNodeOfFrame(false) ? GetAncestorNodeOfFrame(false)->GetId() : 0,
2026 layoutConstraint.ToString().c_str());
2027 Measure(layoutConstraint);
2028 }
2029 {
2030 ACE_SCOPED_TRACE("CreateTaskLayout[%s][self:%d][parent:%d]", GetTag().c_str(), GetId(),
2031 GetAncestorNodeOfFrame(false) ? GetAncestorNodeOfFrame(false)->GetId() : 0);
2032 Layout();
2033 }
2034 }
2035 SetRootMeasureNode(false);
2036 }
2037
CreateRenderTask(bool forceUseMainThread)2038 std::optional<UITask> FrameNode::CreateRenderTask(bool forceUseMainThread)
2039 {
2040 if (!isRenderDirtyMarked_) {
2041 return std::nullopt;
2042 }
2043 auto wrapper = CreatePaintWrapper();
2044 CHECK_NULL_RETURN(wrapper, std::nullopt);
2045 auto task = [weak = WeakClaim(this), wrapper, paintProperty = paintProperty_]() {
2046 auto self = weak.Upgrade();
2047 ACE_SCOPED_TRACE("FrameNode[%s][id:%d]::RenderTask", self->GetTag().c_str(), self->GetId());
2048 ArkUIPerfMonitor::GetInstance().RecordRenderNode();
2049 wrapper->FlushRender();
2050 paintProperty->CleanDirty();
2051 auto eventHub = self->GetEventHub<NG::EventHub>();
2052 if (self->GetInspectorId() || (eventHub && eventHub->HasNDKDrawCompletedCallback())) {
2053 auto pipeline = PipelineContext::GetCurrentContext();
2054 CHECK_NULL_VOID(pipeline);
2055 pipeline->SetNeedRenderNode(weak);
2056 }
2057 };
2058 if (forceUseMainThread || wrapper->CheckShouldRunOnMain()) {
2059 return UITask(std::move(task), MAIN_TASK);
2060 }
2061 return UITask(std::move(task), wrapper->CanRunOnWhichThread());
2062 }
2063
GetLayoutConstraint() const2064 LayoutConstraintF FrameNode::GetLayoutConstraint() const
2065 {
2066 if (geometryNode_->GetParentLayoutConstraint().has_value()) {
2067 return geometryNode_->GetParentLayoutConstraint().value();
2068 }
2069 LayoutConstraintF layoutConstraint;
2070 layoutConstraint.scaleProperty = ScaleProperty::CreateScaleProperty();
2071 auto rootWidth = PipelineContext::GetCurrentRootWidth();
2072 auto rootHeight = PipelineContext::GetCurrentRootHeight();
2073 layoutConstraint.percentReference.SetWidth(rootWidth);
2074 layoutConstraint.percentReference.SetHeight(rootHeight);
2075 layoutConstraint.maxSize.SetWidth(rootWidth);
2076 layoutConstraint.maxSize.SetHeight(rootHeight);
2077 return layoutConstraint;
2078 }
2079
UpdateLayoutPropertyFlag()2080 void FrameNode::UpdateLayoutPropertyFlag()
2081 {
2082 auto selfFlag = layoutProperty_->GetPropertyChangeFlag();
2083 if (!CheckUpdateByChildRequest(selfFlag)) {
2084 return;
2085 }
2086 if (CheckForceParentMeasureFlag(selfFlag)) {
2087 return;
2088 }
2089 auto flag = PROPERTY_UPDATE_NORMAL;
2090 const auto& children = GetChildren();
2091 for (const auto& child : children) {
2092 child->UpdateLayoutPropertyFlag();
2093 child->AdjustParentLayoutFlag(flag);
2094 if (CheckForceParentMeasureFlag(selfFlag)) {
2095 break;
2096 }
2097 }
2098 if (CheckForceParentMeasureFlag(flag)) {
2099 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
2100 }
2101 }
2102
ForceUpdateLayoutPropertyFlag(PropertyChangeFlag propertyChangeFlag)2103 void FrameNode::ForceUpdateLayoutPropertyFlag(PropertyChangeFlag propertyChangeFlag)
2104 {
2105 layoutProperty_->UpdatePropertyChangeFlag(propertyChangeFlag);
2106 }
2107
AdjustParentLayoutFlag(PropertyChangeFlag & flag)2108 void FrameNode::AdjustParentLayoutFlag(PropertyChangeFlag& flag)
2109 {
2110 flag = flag | layoutProperty_->GetPropertyChangeFlag();
2111 }
2112
CreateLayoutWrapper(bool forceMeasure,bool forceLayout)2113 RefPtr<LayoutWrapperNode> FrameNode::CreateLayoutWrapper(bool forceMeasure, bool forceLayout)
2114 {
2115 return UpdateLayoutWrapper(nullptr, forceMeasure, forceLayout);
2116 }
2117
UpdateLayoutWrapper(RefPtr<LayoutWrapperNode> layoutWrapper,bool forceMeasure,bool forceLayout)2118 RefPtr<LayoutWrapperNode> FrameNode::UpdateLayoutWrapper(
2119 RefPtr<LayoutWrapperNode> layoutWrapper, bool forceMeasure, bool forceLayout)
2120 {
2121 CHECK_NULL_RETURN(layoutProperty_, nullptr);
2122 CHECK_NULL_RETURN(pattern_, nullptr);
2123 if (layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE) == VisibleType::GONE) {
2124 if (!layoutWrapper) {
2125 layoutWrapper =
2126 MakeRefPtr<LayoutWrapperNode>(WeakClaim(this), MakeRefPtr<GeometryNode>(), layoutProperty_->Clone());
2127 } else {
2128 layoutWrapper->Update(WeakClaim(this), MakeRefPtr<GeometryNode>(), layoutProperty_->Clone());
2129 }
2130 layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(nullptr, true, true));
2131 isLayoutDirtyMarked_ = false;
2132 return layoutWrapper;
2133 }
2134
2135 pattern_->BeforeCreateLayoutWrapper();
2136 if (forceMeasure) {
2137 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
2138 }
2139 if (forceLayout) {
2140 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_LAYOUT);
2141 }
2142 auto flag = layoutProperty_->GetPropertyChangeFlag();
2143 // It is necessary to copy the layoutProperty property to prevent the layoutProperty property from being
2144 // modified during the layout process, resulting in the problem of judging whether the front-end setting value
2145 // changes the next time js is executed.
2146 if (!layoutWrapper) {
2147 layoutWrapper =
2148 MakeRefPtr<LayoutWrapperNode>(WeakClaim(this), geometryNode_->Clone(), layoutProperty_->Clone());
2149 } else {
2150 layoutWrapper->Update(WeakClaim(this), geometryNode_->Clone(), layoutProperty_->Clone());
2151 }
2152 do {
2153 if (CheckNeedMeasure(flag) || forceMeasure) {
2154 layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm()));
2155 bool forceChildMeasure = CheckMeasureFlag(flag) || CheckMeasureSelfAndChildFlag(flag) || forceMeasure;
2156 UpdateChildrenLayoutWrapper(layoutWrapper, forceChildMeasure, false);
2157 break;
2158 }
2159 if (CheckNeedLayout(flag) || forceLayout) {
2160 layoutWrapper->SetLayoutAlgorithm(
2161 MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm(), true, false));
2162 UpdateChildrenLayoutWrapper(layoutWrapper, false, false);
2163 break;
2164 }
2165 layoutWrapper->SetLayoutAlgorithm(MakeRefPtr<LayoutAlgorithmWrapper>(nullptr, true, true));
2166 } while (false);
2167 // check position flag.
2168 layoutWrapper->SetOutOfLayout(renderContext_->HasPosition());
2169 layoutWrapper->SetActive(isActive_);
2170 layoutWrapper->SetIsOverlayNode(layoutProperty_->IsOverlayNode());
2171 isLayoutDirtyMarked_ = false;
2172 return layoutWrapper;
2173 }
2174
UpdateChildrenLayoutWrapper(const RefPtr<LayoutWrapperNode> & self,bool forceMeasure,bool forceLayout)2175 void FrameNode::UpdateChildrenLayoutWrapper(const RefPtr<LayoutWrapperNode>& self, bool forceMeasure, bool forceLayout)
2176 {
2177 const auto& children = GetChildren();
2178 for (const auto& child : children) {
2179 child->AdjustLayoutWrapperTree(self, forceMeasure, forceLayout);
2180 }
2181 }
2182
AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode> & parent,bool forceMeasure,bool forceLayout)2183 void FrameNode::AdjustLayoutWrapperTree(const RefPtr<LayoutWrapperNode>& parent, bool forceMeasure, bool forceLayout)
2184 {
2185 ACE_DCHECK(parent);
2186 CHECK_NULL_VOID(layoutProperty_);
2187 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
2188 if (geometryTransition != nullptr && geometryTransition->IsNodeOutAndActive(WeakClaim(this))) {
2189 return;
2190 }
2191 auto layoutWrapper = CreateLayoutWrapper(forceMeasure, forceLayout);
2192 parent->AppendChild(layoutWrapper, layoutProperty_->IsOverlayNode());
2193 }
2194
GetContentModifier()2195 RefPtr<ContentModifier> FrameNode::GetContentModifier()
2196 {
2197 CHECK_NULL_RETURN(pattern_, nullptr);
2198 auto wrapper = CreatePaintWrapper();
2199 CHECK_NULL_RETURN(wrapper, nullptr);
2200 auto paintMethod = pattern_->CreateNodePaintMethod();
2201 if (!paintMethod || extensionHandler_ || renderContext_->GetAccessibilityFocus().value_or(false)) {
2202 paintMethod = pattern_->CreateDefaultNodePaintMethod();
2203 }
2204 CHECK_NULL_RETURN(paintMethod, nullptr);
2205 auto contentModifier = DynamicCast<ContentModifier>(paintMethod->GetContentModifier(AceType::RawPtr(wrapper)));
2206 return contentModifier;
2207 }
2208
CreatePaintWrapper()2209 RefPtr<PaintWrapper> FrameNode::CreatePaintWrapper()
2210 {
2211 pattern_->BeforeCreatePaintWrapper();
2212 isRenderDirtyMarked_ = false;
2213 auto paintMethod = pattern_->CreateNodePaintMethod();
2214 if (paintMethod || extensionHandler_ || renderContext_->GetAccessibilityFocus().value_or(false)) {
2215 // It is necessary to copy the layoutProperty property to prevent the paintProperty_ property from being
2216 // modified during the paint process, resulting in the problem of judging whether the front-end setting value
2217 // changes the next time js is executed.
2218 if (!paintMethod) {
2219 paintMethod = pattern_->CreateDefaultNodePaintMethod();
2220 }
2221
2222 auto paintWrapper = MakeRefPtr<PaintWrapper>(
2223 renderContext_, geometryNode_->Clone(), paintProperty_->Clone(), extensionHandler_);
2224 paintWrapper->SetNodePaintMethod(paintMethod);
2225 return paintWrapper;
2226 }
2227 return nullptr;
2228 }
2229
PostIdleTask(std::function<void (int64_t deadline,bool canUseLongPredictTask)> && task)2230 void FrameNode::PostIdleTask(std::function<void(int64_t deadline, bool canUseLongPredictTask)>&& task)
2231 {
2232 auto context = GetContext();
2233 CHECK_NULL_VOID(context);
2234 context->AddPredictTask(std::move(task));
2235 }
2236
UpdateLayoutConstraint(const MeasureProperty & calcLayoutConstraint)2237 void FrameNode::UpdateLayoutConstraint(const MeasureProperty& calcLayoutConstraint)
2238 {
2239 layoutProperty_->UpdateCalcLayoutProperty(calcLayoutConstraint);
2240 }
2241
RebuildRenderContextTree()2242 void FrameNode::RebuildRenderContextTree()
2243 {
2244 if (!needSyncRenderTree_) {
2245 return;
2246 }
2247 auto pipeline = GetContextRefPtr();
2248 if (pipeline && !pipeline->CheckThreadSafe()) {
2249 LOGW("RebuildRenderContextTree doesn't run on UI thread!");
2250 }
2251 frameChildren_.clear();
2252 std::list<RefPtr<FrameNode>> children;
2253 // generate full children list, including disappear children.
2254 GenerateOneDepthVisibleFrameWithTransition(children);
2255 if (overlayNode_) {
2256 auto property = overlayNode_->GetLayoutProperty();
2257 if (property && property->GetVisibilityValue(VisibleType::VISIBLE) == VisibleType::VISIBLE) {
2258 children.push_back(overlayNode_);
2259 }
2260 }
2261 for (const auto& child : children) {
2262 frameChildren_.emplace(child);
2263 }
2264 renderContext_->RebuildFrame(this, children);
2265 pattern_->OnRebuildFrame();
2266 needSyncRenderTree_ = false;
2267 }
2268
MarkModifyDone()2269 void FrameNode::MarkModifyDone()
2270 {
2271 pattern_->OnModifyDone();
2272 auto pipeline = PipelineContext::GetCurrentContextSafely();
2273 if (pipeline) {
2274 auto privacyManager = pipeline->GetPrivacySensitiveManager();
2275 if (privacyManager) {
2276 if (IsPrivacySensitive()) {
2277 LOGI("store sensitive node, %{public}d", GetId());
2278 privacyManager->StoreNode(AceType::WeakClaim(this));
2279 } else {
2280 privacyManager->RemoveNode(AceType::WeakClaim(this));
2281 }
2282 }
2283 }
2284 if (!isRestoreInfoUsed_) {
2285 isRestoreInfoUsed_ = true;
2286 int32_t restoreId = GetRestoreId();
2287 if (pipeline && restoreId >= 0) {
2288 // store distribute node
2289 pipeline->StoreNode(restoreId, AceType::WeakClaim(this));
2290 // restore distribute node info
2291 std::string restoreInfo;
2292 if (pipeline->GetRestoreInfo(restoreId, restoreInfo)) {
2293 pattern_->OnRestoreInfo(restoreInfo);
2294 }
2295 }
2296 }
2297 eventHub_->MarkModifyDone();
2298 renderContext_->OnModifyDone();
2299 #if (defined(__aarch64__) || defined(__x86_64__))
2300 if (Recorder::IsCacheAvaliable()) {
2301 auto pipeline = PipelineContext::GetCurrentContext();
2302 CHECK_NULL_VOID(pipeline);
2303 pipeline->AddAfterRenderTask([weak = WeakPtr(pattern_)]() {
2304 auto pattern = weak.Upgrade();
2305 CHECK_NULL_VOID(pattern);
2306 pattern->OnAfterModifyDone();
2307 });
2308 }
2309 #endif
2310 }
2311
OnMountToParentDone()2312 void FrameNode::OnMountToParentDone()
2313 {
2314 pattern_->OnMountToParentDone();
2315 }
2316
AfterMountToParent()2317 void FrameNode::AfterMountToParent()
2318 {
2319 if (pattern_) {
2320 pattern_->AfterMountToParent();
2321 }
2322 }
2323
FlushUpdateAndMarkDirty()2324 void FrameNode::FlushUpdateAndMarkDirty()
2325 {
2326 MarkDirtyNode();
2327 }
2328
MarkDirtyNode(PropertyChangeFlag extraFlag)2329 void FrameNode::MarkDirtyNode(PropertyChangeFlag extraFlag)
2330 {
2331 if (IsFreeze()) {
2332 // store the flag.
2333 layoutProperty_->UpdatePropertyChangeFlag(extraFlag);
2334 paintProperty_->UpdatePropertyChangeFlag(extraFlag);
2335 return;
2336 }
2337 if (CheckNeedMakePropertyDiff(extraFlag)) {
2338 if (isPropertyDiffMarked_) {
2339 return;
2340 }
2341 auto context = GetContextWithCheck();
2342 CHECK_NULL_VOID(context);
2343 context->AddDirtyPropertyNode(Claim(this));
2344 isPropertyDiffMarked_ = true;
2345 return;
2346 }
2347 MarkDirtyNode(IsMeasureBoundary(), IsRenderBoundary(), extraFlag);
2348 }
2349
ProcessFreezeNode()2350 void FrameNode::ProcessFreezeNode()
2351 {
2352 MarkDirtyNode();
2353 }
2354
OnFreezeStateChange()2355 void FrameNode::OnFreezeStateChange()
2356 {
2357 if (IsFreeze()) {
2358 return;
2359 }
2360 // unlock freeze, mark dirty to process freeze node.
2361 auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
2362 auto paintFlag = paintProperty_->GetPropertyChangeFlag();
2363 if (CheckNoChanged(layoutFlag | paintFlag)) {
2364 return;
2365 }
2366 auto pipeline = GetContext();
2367 CHECK_NULL_VOID(pipeline);
2368 pipeline->AddDirtyFreezeNode(this);
2369 }
2370
GetAncestorNodeOfFrame(bool checkBoundary) const2371 RefPtr<FrameNode> FrameNode::GetAncestorNodeOfFrame(bool checkBoundary) const
2372 {
2373 if (checkBoundary && IsWindowBoundary()) {
2374 return nullptr;
2375 }
2376 auto parent = GetParent();
2377 while (parent) {
2378 auto parentFrame = DynamicCast<FrameNode>(parent);
2379 if (parentFrame) {
2380 return parentFrame;
2381 }
2382 parent = parent->GetParent();
2383 }
2384 return nullptr;
2385 }
2386
GetPageNode()2387 RefPtr<FrameNode> FrameNode::GetPageNode()
2388 {
2389 if (GetTag() == "page") {
2390 return Claim(this);
2391 }
2392 auto parent = GetParent();
2393 while (parent && parent->GetTag() != "page") {
2394 parent = parent->GetParent();
2395 }
2396 return AceType::DynamicCast<FrameNode>(parent);
2397 }
2398
GetFirstAutoFillContainerNode()2399 RefPtr<FrameNode> FrameNode::GetFirstAutoFillContainerNode()
2400 {
2401 if (IsAutoFillContainerNode()) {
2402 return Claim(this);
2403 }
2404 auto parent = GetParent();
2405 while (parent && !parent->IsAutoFillContainerNode()) {
2406 parent = parent->GetParent();
2407 }
2408 return AceType::DynamicCast<FrameNode>(parent);
2409 }
2410
NotifyFillRequestSuccess(RefPtr<ViewDataWrap> viewDataWrap,RefPtr<PageNodeInfoWrap> nodeWrap,AceAutoFillType autoFillType)2411 void FrameNode::NotifyFillRequestSuccess(
2412 RefPtr<ViewDataWrap> viewDataWrap, RefPtr<PageNodeInfoWrap> nodeWrap, AceAutoFillType autoFillType)
2413 {
2414 if (pattern_) {
2415 pattern_->NotifyFillRequestSuccess(viewDataWrap, nodeWrap, autoFillType);
2416 }
2417 }
2418
NotifyFillRequestFailed(int32_t errCode,const std::string & fillContent,bool isPopup)2419 void FrameNode::NotifyFillRequestFailed(int32_t errCode, const std::string& fillContent, bool isPopup)
2420 {
2421 if (pattern_) {
2422 pattern_->NotifyFillRequestFailed(errCode, fillContent, isPopup);
2423 }
2424 }
2425
MarkNeedRenderOnly()2426 void FrameNode::MarkNeedRenderOnly()
2427 {
2428 MarkNeedRender(IsRenderBoundary());
2429 }
2430
MarkNeedRender(bool isRenderBoundary)2431 void FrameNode::MarkNeedRender(bool isRenderBoundary)
2432 {
2433 auto context = GetContext();
2434 CHECK_NULL_VOID(context);
2435 // If it has dirtyLayoutBox, need to mark dirty after layout done.
2436 paintProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_RENDER);
2437 if (isRenderDirtyMarked_ || isLayoutDirtyMarked_) {
2438 return;
2439 }
2440 isRenderDirtyMarked_ = true;
2441 if (isRenderBoundary) {
2442 context->AddDirtyRenderNode(Claim(this));
2443 return;
2444 }
2445 auto parent = GetAncestorNodeOfFrame(false);
2446 if (parent) {
2447 parent->MarkDirtyNode(PROPERTY_UPDATE_RENDER_BY_CHILD_REQUEST);
2448 }
2449 }
2450
RequestParentDirty()2451 bool FrameNode::RequestParentDirty()
2452 {
2453 auto parent = GetAncestorNodeOfFrame(false);
2454 CHECK_NULL_RETURN(parent, false);
2455 parent->MarkDirtyNode(PROPERTY_UPDATE_BY_CHILD_REQUEST);
2456 return true;
2457 }
2458
MarkDirtyNode(bool isMeasureBoundary,bool isRenderBoundary,PropertyChangeFlag extraFlag)2459 void FrameNode::MarkDirtyNode(bool isMeasureBoundary, bool isRenderBoundary, PropertyChangeFlag extraFlag)
2460 {
2461 layoutProperty_->UpdatePropertyChangeFlag(extraFlag);
2462 paintProperty_->UpdatePropertyChangeFlag(extraFlag);
2463 auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
2464 auto paintFlag = paintProperty_->GetPropertyChangeFlag();
2465 if (CheckNoChanged(layoutFlag | paintFlag)) {
2466 return;
2467 }
2468 auto context = GetContext();
2469 CHECK_NULL_VOID(context);
2470
2471 if (CheckNeedRequestMeasureAndLayout(layoutFlag)) {
2472 if ((!isMeasureBoundary && IsNeedRequestParentMeasure())) {
2473 if (RequestParentDirty()) {
2474 return;
2475 }
2476 }
2477 if (isLayoutDirtyMarked_) {
2478 return;
2479 }
2480 isLayoutDirtyMarked_ = true;
2481 context->AddDirtyLayoutNode(Claim(this));
2482 return;
2483 }
2484 layoutProperty_->CleanDirty();
2485 MarkNeedRender(isRenderBoundary);
2486 }
2487
IsNeedRequestParentMeasure() const2488 bool FrameNode::IsNeedRequestParentMeasure() const
2489 {
2490 auto layoutFlag = layoutProperty_->GetPropertyChangeFlag();
2491 if (layoutFlag == PROPERTY_UPDATE_BY_CHILD_REQUEST) {
2492 const auto& calcLayoutConstraint = layoutProperty_->GetCalcLayoutConstraint();
2493 if (calcLayoutConstraint && calcLayoutConstraint->selfIdealSize &&
2494 calcLayoutConstraint->selfIdealSize->IsValid()) {
2495 return false;
2496 }
2497 }
2498 return CheckNeedRequestParentMeasure(layoutFlag);
2499 }
2500
OnGenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>> & visibleList)2501 void FrameNode::OnGenerateOneDepthVisibleFrame(std::list<RefPtr<FrameNode>>& visibleList)
2502 {
2503 if (isLayoutNode_) {
2504 UINode::GenerateOneDepthVisibleFrame(visibleList);
2505 if (overlayNode_) {
2506 visibleList.emplace_back(overlayNode_);
2507 }
2508 return;
2509 }
2510 if (isActive_ && IsVisible()) {
2511 visibleList.emplace_back(Claim(this));
2512 }
2513 }
2514
OnGenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>> & allList)2515 void FrameNode::OnGenerateOneDepthAllFrame(std::list<RefPtr<FrameNode>>& allList)
2516 {
2517 allList.emplace_back(Claim(this));
2518 }
2519
OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>> & visibleList)2520 void FrameNode::OnGenerateOneDepthVisibleFrameWithTransition(std::list<RefPtr<FrameNode>>& visibleList)
2521 {
2522 if (isLayoutNode_) {
2523 UINode::GenerateOneDepthVisibleFrameWithTransition(visibleList);
2524 if (overlayNode_) {
2525 visibleList.emplace_back(overlayNode_);
2526 }
2527 return;
2528 }
2529
2530 auto context = GetRenderContext();
2531 CHECK_NULL_VOID(context);
2532 // skip if 1.not active or 2.not visible and has no transition out animation.
2533 if (!isActive_ || (!IsVisible() && !context->HasTransitionOutAnimation())) {
2534 return;
2535 }
2536 visibleList.emplace_back(Claim(this));
2537 }
2538
OnGenerateOneDepthVisibleFrameWithOffset(std::list<RefPtr<FrameNode>> & visibleList,OffsetF & offset)2539 void FrameNode::OnGenerateOneDepthVisibleFrameWithOffset(std::list<RefPtr<FrameNode>>& visibleList, OffsetF& offset)
2540 {
2541 if (isLayoutNode_) {
2542 isFind_ = true;
2543 offset += GetGeometryNode()->GetFrameOffset();
2544 UINode::GenerateOneDepthVisibleFrameWithOffset(visibleList, offset);
2545 if (overlayNode_) {
2546 visibleList.emplace_back(overlayNode_);
2547 }
2548 return;
2549 }
2550
2551 auto context = GetRenderContext();
2552 CHECK_NULL_VOID(context);
2553 // skip if 1.not active or 2.not visible and has no transition out animation.
2554 if (!isActive_ || (!IsVisible() && !context->HasTransitionOutAnimation())) {
2555 return;
2556 }
2557 visibleList.emplace_back(Claim(this));
2558 }
2559
IsMeasureBoundary()2560 bool FrameNode::IsMeasureBoundary()
2561 {
2562 return isMeasureBoundary_ || pattern_->IsMeasureBoundary();
2563 }
2564
IsRenderBoundary()2565 bool FrameNode::IsRenderBoundary()
2566 {
2567 return pattern_->IsRenderBoundary();
2568 }
2569
GetPattern() const2570 const RefPtr<Pattern>& FrameNode::GetPattern() const
2571 {
2572 return pattern_;
2573 }
2574
IsAtomicNode() const2575 bool FrameNode::IsAtomicNode() const
2576 {
2577 return pattern_->IsAtomicNode();
2578 }
2579
GetHitTestMode() const2580 HitTestMode FrameNode::GetHitTestMode() const
2581 {
2582 auto gestureHub = eventHub_->GetGestureEventHub();
2583 return gestureHub ? gestureHub->GetHitTestMode() : HitTestMode::HTMDEFAULT;
2584 }
2585
SetHitTestMode(HitTestMode mode)2586 void FrameNode::SetHitTestMode(HitTestMode mode)
2587 {
2588 auto gestureHub = eventHub_->GetOrCreateGestureEventHub();
2589 CHECK_NULL_VOID(gestureHub);
2590 gestureHub->SetHitTestMode(mode);
2591 }
2592
GetTouchable() const2593 bool FrameNode::GetTouchable() const
2594 {
2595 auto gestureHub = eventHub_->GetGestureEventHub();
2596 return gestureHub ? gestureHub->GetTouchable() : true;
2597 }
2598
GetMonopolizeEvents() const2599 bool FrameNode::GetMonopolizeEvents() const
2600 {
2601 auto gestureHub = eventHub_->GetGestureEventHub();
2602 return gestureHub ? gestureHub->GetMonopolizeEvents() : false;
2603 }
2604
GetPaintRectWithTransform() const2605 RectF FrameNode::GetPaintRectWithTransform() const
2606 {
2607 return renderContext_->GetPaintRectWithTransform();
2608 }
2609
GetTransformScale() const2610 VectorF FrameNode::GetTransformScale() const
2611 {
2612 return renderContext_->GetTransformScaleValue({ 1.0f, 1.0f });
2613 }
2614
IsPaintRectWithTransformValid()2615 bool FrameNode::IsPaintRectWithTransformValid()
2616 {
2617 auto paintRectWithTransform = renderContext_->GetPaintRectWithTransform();
2618 if (NearZero(paintRectWithTransform.Width()) || NearZero(paintRectWithTransform.Height())) {
2619 return true;
2620 }
2621 return false;
2622 }
2623
IsOutOfTouchTestRegion(const PointF & parentRevertPoint,const TouchEvent & touchEvent)2624 bool FrameNode::IsOutOfTouchTestRegion(const PointF& parentRevertPoint, const TouchEvent& touchEvent)
2625 {
2626 bool isInChildRegion = false;
2627 auto paintRect = renderContext_->GetPaintRectWithoutTransform();
2628 if (pattern_->IsResponseRegionExpandingNeededForStylus(touchEvent)) {
2629 paintRect = pattern_->ExpandDefaultResponseRegion(paintRect);
2630 }
2631 auto responseRegionList = GetResponseRegionList(paintRect, static_cast<int32_t>(touchEvent.sourceType));
2632
2633 auto revertPoint = parentRevertPoint;
2634 MapPointTo(revertPoint, GetOrRefreshRevertMatrixFromCache());
2635 auto subRevertPoint = revertPoint - paintRect.GetOffset();
2636 auto clip = renderContext_->GetClipEdge().value_or(false);
2637 if (!InResponseRegionList(revertPoint, responseRegionList) || !GetTouchable() ||
2638 IsPaintRectWithTransformValid()) {
2639 if (clip) {
2640 return true;
2641 }
2642 for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
2643 const auto& child = iter->Upgrade();
2644 if (child && !child->IsOutOfTouchTestRegion(subRevertPoint, touchEvent)) {
2645 isInChildRegion = true;
2646 break;
2647 }
2648 }
2649 if (!isInChildRegion) {
2650 return true;
2651 }
2652 }
2653 return false;
2654 }
2655
AddJudgeToTargetComponent(RefPtr<TargetComponent> & targetComponent)2656 void FrameNode::AddJudgeToTargetComponent(RefPtr<TargetComponent>& targetComponent)
2657 {
2658 auto gestureHub = eventHub_->GetGestureEventHub();
2659 if (gestureHub) {
2660 auto callback = gestureHub->GetOnGestureJudgeBeginCallback();
2661 targetComponent->SetOnGestureJudgeBegin(std::move(callback));
2662 auto callbackNative = gestureHub->GetOnGestureJudgeNativeBeginCallback();
2663 if (callbackNative) {
2664 targetComponent->SetOnGestureJudgeNativeBegin(std::move(callbackNative));
2665 }
2666
2667 if (!targetComponent->IsInnerNodeGestureRecognizerJudgeSet()) {
2668 auto gestureRecognizerJudgeCallback = gestureHub->GetOnGestureRecognizerJudgeBegin();
2669 targetComponent->SetOnGestureRecognizerJudgeBegin(std::move(gestureRecognizerJudgeCallback));
2670 }
2671
2672 if (GetExposeInnerGestureFlag()) {
2673 auto pattern = GetPattern();
2674 if (pattern) {
2675 auto gestureRecognizerJudgeCallback = gestureHub->GetOnGestureRecognizerJudgeBegin();
2676 pattern->AddInnerOnGestureRecognizerJudgeBegin(std::move(gestureRecognizerJudgeCallback));
2677 }
2678 }
2679 }
2680 }
2681
TouchTest(const PointF & globalPoint,const PointF & parentLocalPoint,const PointF & parentRevertPoint,TouchRestrict & touchRestrict,TouchTestResult & result,int32_t touchId,ResponseLinkResult & responseLinkResult,bool isDispatch)2682 HitTestResult FrameNode::TouchTest(const PointF& globalPoint, const PointF& parentLocalPoint,
2683 const PointF& parentRevertPoint, TouchRestrict& touchRestrict, TouchTestResult& result, int32_t touchId,
2684 ResponseLinkResult& responseLinkResult, bool isDispatch)
2685 {
2686 if (!isActive_ || !eventHub_->IsEnabled()) {
2687 TAG_LOGW(AceLogTag::ACE_UIEVENT, "%{public}s is inActive, need't do touch test", GetTag().c_str());
2688 return HitTestResult::OUT_OF_REGION;
2689 }
2690 auto paintRect = renderContext_->GetPaintRectWithTransform();
2691 auto origRect = renderContext_->GetPaintRectWithoutTransform();
2692 auto localMat = renderContext_->GetLocalTransformMatrix();
2693 if (!touchRestrict.touchEvent.isMouseTouchTest) {
2694 localMat_ = localMat;
2695 }
2696 int32_t parentId = -1;
2697 auto parent = GetAncestorNodeOfFrame(true);
2698 if (parent) {
2699 parentId = parent->GetId();
2700 }
2701
2702 auto defaultResponseRegion = origRect;
2703 if (pattern_->IsResponseRegionExpandingNeededForStylus(touchRestrict.touchEvent)) {
2704 defaultResponseRegion = pattern_->ExpandDefaultResponseRegion(origRect);
2705 }
2706 auto responseRegionList =
2707 GetResponseRegionList(defaultResponseRegion, static_cast<int32_t>(touchRestrict.sourceType));
2708 if (SystemProperties::GetDebugEnabled()) {
2709 TAG_LOGD(AceLogTag::ACE_UIEVENT, "TouchTest: point is " SEC_PLD(%{public}s) " in %{public}s, depth: %{public}d",
2710 SEC_PARAM(parentRevertPoint.ToString().c_str()), GetTag().c_str(), GetDepth());
2711 for ([[maybe_unused]] const auto& rect : responseRegionList) {
2712 TAG_LOGD(AceLogTag::ACE_UIEVENT, "TouchTest: responseRegionList is " SEC_PLD(%{public}s)
2713 ", point is " SEC_PLD(%{public}s),
2714 SEC_PARAM(rect.ToString().c_str()), SEC_PARAM(parentRevertPoint.ToString().c_str()));
2715 }
2716 }
2717 {
2718 ACE_DEBUG_SCOPED_TRACE("FrameNode::IsOutOfTouchTestRegion");
2719 bool isOutOfRegion = IsOutOfTouchTestRegion(parentRevertPoint, touchRestrict.touchEvent);
2720 AddFrameNodeSnapshot(!isOutOfRegion, parentId, responseRegionList, touchRestrict.touchTestType);
2721 if ((!isDispatch) && isOutOfRegion) {
2722 return HitTestResult::OUT_OF_REGION;
2723 }
2724 }
2725
2726 RefPtr<TargetComponent> targetComponent;
2727 if (targetComponent_.Upgrade()) {
2728 targetComponent = targetComponent_.Upgrade();
2729 } else {
2730 targetComponent = MakeRefPtr<TargetComponent>();
2731 targetComponent_ = targetComponent;
2732 }
2733 targetComponent->SetNode(WeakClaim(this));
2734
2735 HitTestResult testResult = HitTestResult::OUT_OF_REGION;
2736 bool preventBubbling = false;
2737 // Child nodes are repackaged into gesture groups (parallel gesture groups, exclusive gesture groups, etc.)
2738 // based on the gesture attributes set by the current parent node (high and low priority, parallel gestures,
2739 // etc.), the newComingTargets is the template object to collect child nodes gesture and used by gestureHub to
2740 // pack gesture group.
2741 TouchTestResult newComingTargets;
2742 auto tmp = parentLocalPoint - paintRect.GetOffset();
2743 auto preLocation = tmp;
2744 renderContext_->GetPointWithTransform(tmp);
2745 const auto localPoint = tmp;
2746 auto localTransformOffset = preLocation - localPoint;
2747
2748 auto revertPoint = parentRevertPoint;
2749 MapPointTo(revertPoint, GetOrRefreshRevertMatrixFromCache());
2750 auto subRevertPoint = revertPoint - origRect.GetOffset();
2751 bool consumed = false;
2752
2753 HitTestMode onTouchInterceptresult = HitTestMode::HTMDEFAULT;
2754 if (touchRestrict.inputEventType != InputEventType::MOUSE_BUTTON) {
2755 onTouchInterceptresult = TriggerOnTouchIntercept(touchRestrict.touchEvent);
2756 }
2757 TouchResult touchRes;
2758 if (onTouchInterceptresult != HitTestMode::HTMBLOCK) {
2759 std::vector<TouchTestInfo> touchInfos;
2760 CollectTouchInfos(globalPoint, subRevertPoint, touchInfos);
2761 touchRes = GetOnChildTouchTestRet(touchInfos);
2762 if ((touchRes.strategy != TouchTestStrategy::DEFAULT) && touchRes.id.empty()) {
2763 TAG_LOGW(AceLogTag::ACE_UIEVENT, "onChildTouchTest result is: "
2764 "id = " SEC_PLD(%{public}s) ", strategy = %{public}d.",
2765 SEC_PARAM(touchRes.id.c_str()), static_cast<int32_t>(touchRes.strategy));
2766 touchRes.strategy = TouchTestStrategy::DEFAULT;
2767 }
2768
2769 auto childNode = GetDispatchFrameNode(touchRes);
2770 if (childNode != nullptr) {
2771 TAG_LOGD(AceLogTag::ACE_UIEVENT, SEC_PLD(%{public}s) " do TouchTest, parameter isDispatch is true.",
2772 SEC_PARAM(childNode->GetInspectorId()->c_str()));
2773 auto hitResult = childNode->TouchTest(globalPoint, localPoint, subRevertPoint, touchRestrict,
2774 newComingTargets, touchId, responseLinkResult, true);
2775 if (touchRes.strategy == TouchTestStrategy::FORWARD ||
2776 touchRes.strategy == TouchTestStrategy::FORWARD_COMPETITION) {
2777 touchRestrict.childTouchTestList.emplace_back(touchRes.id);
2778 }
2779 if (hitResult == HitTestResult::STOP_BUBBLING) {
2780 preventBubbling = true;
2781 consumed = true;
2782 }
2783
2784 if (hitResult == HitTestResult::BUBBLING) {
2785 consumed = true;
2786 }
2787 }
2788 }
2789
2790 for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
2791 if (GetHitTestMode() == HitTestMode::HTMBLOCK) {
2792 break;
2793 }
2794 if (onTouchInterceptresult != HitTestMode::HTMBLOCK) {
2795 if (touchRes.strategy == TouchTestStrategy::FORWARD) {
2796 break;
2797 }
2798 }
2799
2800 const auto& child = iter->Upgrade();
2801 if (!child) {
2802 continue;
2803 }
2804 if (onTouchInterceptresult != HitTestMode::HTMBLOCK) {
2805 std::string id;
2806 if (child->GetInspectorId().has_value()) {
2807 id = child->GetInspectorId().value();
2808 }
2809 if (touchRes.strategy == TouchTestStrategy::FORWARD_COMPETITION && touchRes.id == id) {
2810 continue;
2811 }
2812 }
2813
2814 auto childHitResult = child->TouchTest(
2815 globalPoint, localPoint, subRevertPoint, touchRestrict, newComingTargets, touchId, responseLinkResult);
2816 if (childHitResult == HitTestResult::STOP_BUBBLING) {
2817 preventBubbling = true;
2818 consumed = true;
2819 if ((child->GetHitTestMode() == HitTestMode::HTMBLOCK) ||
2820 (child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
2821 (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ||
2822 ((child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT) && IsExclusiveEventForChild())) {
2823 break;
2824 }
2825 }
2826
2827 // In normal process, the node block the brother node.
2828 if (childHitResult == HitTestResult::BUBBLING &&
2829 ((child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
2830 (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ||
2831 ((child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT) && IsExclusiveEventForChild()))) {
2832 consumed = true;
2833 break;
2834 }
2835 }
2836
2837 AddJudgeToTargetComponent(targetComponent);
2838
2839 // first update HitTestResult by children status.
2840 if (consumed) {
2841 testResult = preventBubbling ? HitTestResult::STOP_BUBBLING : HitTestResult::BUBBLING;
2842 consumed = false;
2843 } else if (GetHitTestMode() == HitTestMode::HTMBLOCK) {
2844 testResult = HitTestResult::STOP_BUBBLING;
2845 }
2846
2847 if (!preventBubbling && (GetHitTestMode() != HitTestMode::HTMNONE) &&
2848 (isDispatch || (InResponseRegionList(revertPoint, responseRegionList)))) {
2849 pattern_->OnTouchTestHit(touchRestrict.hitTestType);
2850 consumed = true;
2851 if (touchRestrict.hitTestType == SourceType::TOUCH) {
2852 auto gestureHub = eventHub_->GetGestureEventHub();
2853 if (gestureHub) {
2854 TouchTestResult finalResult;
2855 ResponseLinkResult newComingResponseLinkTargets;
2856 const auto coordinateOffset = globalPoint - localPoint - localTransformOffset;
2857 preventBubbling = gestureHub->ProcessTouchTestHit(coordinateOffset, touchRestrict, newComingTargets,
2858 finalResult, touchId, localPoint, targetComponent, newComingResponseLinkTargets);
2859 newComingTargets.swap(finalResult);
2860 TriggerShouldParallelInnerWith(newComingResponseLinkTargets, responseLinkResult);
2861 responseLinkResult.splice(responseLinkResult.end(), std::move(newComingResponseLinkTargets));
2862 }
2863 } else if (touchRestrict.hitTestType == SourceType::MOUSE) {
2864 preventBubbling = ProcessMouseTestHit(globalPoint, localPoint, touchRestrict, newComingTargets);
2865 }
2866 }
2867
2868 result.splice(result.end(), std::move(newComingTargets));
2869 if (touchRestrict.hitTestType == SourceType::TOUCH) {
2870 // combine into exclusive recognizer group.
2871 auto gestureHub = eventHub_->GetGestureEventHub();
2872 if (gestureHub) {
2873 gestureHub->CombineIntoExclusiveRecognizer(globalPoint, localPoint, result, touchId);
2874 }
2875 }
2876
2877 // consumed by children and return result.
2878 if (!consumed) {
2879 return testResult;
2880 }
2881
2882 if (testResult == HitTestResult::OUT_OF_REGION) {
2883 // consume only by self.
2884 if (preventBubbling) {
2885 return HitTestResult::STOP_BUBBLING;
2886 }
2887 return (GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ? HitTestResult::SELF_TRANSPARENT
2888 : HitTestResult::BUBBLING;
2889 }
2890 // consume by self and children.
2891 return testResult;
2892 }
2893
ProcessMouseTestHit(const PointF & globalPoint,const PointF & localPoint,TouchRestrict & touchRestrict,TouchTestResult & newComingTargets)2894 bool FrameNode::ProcessMouseTestHit(const PointF& globalPoint, const PointF& localPoint,
2895 TouchRestrict& touchRestrict, TouchTestResult& newComingTargets)
2896 {
2897 auto mouseHub = eventHub_->GetInputEventHub();
2898 if (!mouseHub) {
2899 return false;
2900 }
2901
2902 const auto coordinateOffset = globalPoint - localPoint;
2903 if (touchRestrict.touchEvent.IsPenHoverEvent()) {
2904 return mouseHub->ProcessPenHoverTestHit(coordinateOffset, newComingTargets);
2905 }
2906
2907 return mouseHub->ProcessMouseTestHit(coordinateOffset, newComingTargets);
2908 }
2909
GetResponseRegionList(const RectF & rect,int32_t sourceType)2910 std::vector<RectF> FrameNode::GetResponseRegionList(const RectF& rect, int32_t sourceType)
2911 {
2912 std::vector<RectF> responseRegionList;
2913 auto gestureHub = eventHub_->GetGestureEventHub();
2914 if (!gestureHub) {
2915 responseRegionList.emplace_back(rect);
2916 return responseRegionList;
2917 }
2918 auto scaleProperty = ScaleProperty::CreateScaleProperty();
2919 bool isMouseEvent = (static_cast<SourceType>(sourceType) == SourceType::MOUSE);
2920 if (isMouseEvent) {
2921 if (gestureHub->GetResponseRegion().empty() && (gestureHub->GetMouseResponseRegion().empty())) {
2922 responseRegionList.emplace_back(rect);
2923 return responseRegionList;
2924 }
2925 } else {
2926 if (gestureHub->GetResponseRegion().empty()) {
2927 responseRegionList.emplace_back(rect);
2928 return responseRegionList;
2929 }
2930 }
2931
2932 if (isMouseEvent && (!gestureHub->GetMouseResponseRegion().empty())) {
2933 for (const auto& region : gestureHub->GetMouseResponseRegion()) {
2934 auto x = ConvertToPx(region.GetOffset().GetX(), scaleProperty, rect.Width());
2935 auto y = ConvertToPx(region.GetOffset().GetY(), scaleProperty, rect.Height());
2936 auto width = ConvertToPx(region.GetWidth(), scaleProperty, rect.Width());
2937 auto height = ConvertToPx(region.GetHeight(), scaleProperty, rect.Height());
2938 if (!x.has_value() || !y.has_value() || !width.has_value() || !height.has_value()) {
2939 continue;
2940 }
2941 RectF mouseRegion(rect.GetOffset().GetX() + x.value(), rect.GetOffset().GetY() + y.value(), width.value(),
2942 height.value());
2943 responseRegionList.emplace_back(mouseRegion);
2944 }
2945 return responseRegionList;
2946 }
2947 for (const auto& region : gestureHub->GetResponseRegion()) {
2948 auto x = ConvertToPx(region.GetOffset().GetX(), scaleProperty, rect.Width());
2949 auto y = ConvertToPx(region.GetOffset().GetY(), scaleProperty, rect.Height());
2950 auto width = ConvertToPx(region.GetWidth(), scaleProperty, rect.Width());
2951 auto height = ConvertToPx(region.GetHeight(), scaleProperty, rect.Height());
2952 if (!x.has_value() || !y.has_value() || !width.has_value() || !height.has_value()) {
2953 continue;
2954 }
2955 RectF responseRegion(
2956 rect.GetOffset().GetX() + x.value(), rect.GetOffset().GetY() + y.value(), width.value(), height.value());
2957 responseRegionList.emplace_back(responseRegion);
2958 }
2959 return responseRegionList;
2960 }
2961
GetResponseRegionListForRecognizer(int32_t sourceType)2962 std::vector<RectF> FrameNode::GetResponseRegionListForRecognizer(int32_t sourceType)
2963 {
2964 auto paintRect = renderContext_->GetPaintRectWithoutTransform();
2965 auto responseRegionList = GetResponseRegionList(paintRect, sourceType);
2966 return responseRegionList;
2967 }
2968
GetResponseRegionListForTouch(const RectF & rect)2969 std::vector<RectF> FrameNode::GetResponseRegionListForTouch(const RectF& rect)
2970 {
2971 ACE_LAYOUT_TRACE_BEGIN("GetResponseRegionListForTouch");
2972 std::vector<RectF> responseRegionList;
2973 auto gestureHub = eventHub_->GetGestureEventHub();
2974 if (!gestureHub) {
2975 ACE_LAYOUT_TRACE_END()
2976 return responseRegionList;
2977 }
2978
2979 bool isAccessibilityClickable = gestureHub->IsAccessibilityClickable();
2980 if (!isAccessibilityClickable) {
2981 ACE_LAYOUT_TRACE_END()
2982 return responseRegionList;
2983 }
2984 auto offset = GetPositionToScreen();
2985 if (gestureHub->GetResponseRegion().empty()) {
2986 RectF rectToScreen{round(offset.GetX()), round(offset.GetY()), round(rect.Width()), round(rect.Height())};
2987 responseRegionList.emplace_back(rectToScreen);
2988 ACE_LAYOUT_TRACE_END()
2989 return responseRegionList;
2990 }
2991
2992 auto scaleProperty = ScaleProperty::CreateScaleProperty();
2993 for (const auto& region : gestureHub->GetResponseRegion()) {
2994 auto x = ConvertToPx(region.GetOffset().GetX(), scaleProperty, rect.Width());
2995 auto y = ConvertToPx(region.GetOffset().GetY(), scaleProperty, rect.Height());
2996 auto width = ConvertToPx(region.GetWidth(), scaleProperty, rect.Width());
2997 auto height = ConvertToPx(region.GetHeight(), scaleProperty, rect.Height());
2998 RectF responseRegion(round(offset.GetX() + x.value()), round(offset.GetY() + y.value()),
2999 round(width.value()), round(height.value()));
3000 responseRegionList.emplace_back(responseRegion);
3001 }
3002 ACE_LAYOUT_TRACE_END()
3003 return responseRegionList;
3004 }
3005
GetResponseRegionListByTraversal(std::vector<RectF> & responseRegionList)3006 void FrameNode::GetResponseRegionListByTraversal(std::vector<RectF>& responseRegionList)
3007 {
3008 CHECK_NULL_VOID(renderContext_);
3009 auto origRect = renderContext_->GetPaintRectWithoutTransform();
3010 auto pipelineContext = GetContext();
3011 CHECK_NULL_VOID(pipelineContext);
3012 auto offset = GetPositionToScreen();
3013 RectF rectToScreen{offset.GetX(), offset.GetY(), origRect.Width(), origRect.Height()};
3014 auto window = pipelineContext->GetCurrentWindowRect();
3015 RectF windowRect{window.Left(), window.Top(), window.Width(), window.Height()};
3016
3017 if (rectToScreen.Left() >= windowRect.Right() || rectToScreen.Right() <= windowRect.Left() ||
3018 rectToScreen.Top() >= windowRect.Bottom() || rectToScreen.Bottom() <= windowRect.Top()) {
3019 return;
3020 }
3021
3022 auto rootRegionList = GetResponseRegionListForTouch(origRect);
3023 if (!rootRegionList.empty()) {
3024 for (auto rect : rootRegionList) {
3025 responseRegionList.push_back(rect.IntersectRectT(windowRect));
3026 }
3027 return;
3028 }
3029 for (auto childWeak = frameChildren_.rbegin(); childWeak != frameChildren_.rend(); ++childWeak) {
3030 const auto& child = childWeak->Upgrade();
3031 if (!child) {
3032 continue;
3033 }
3034 child->GetResponseRegionListByTraversal(responseRegionList);
3035 }
3036 }
3037
InResponseRegionList(const PointF & parentLocalPoint,const std::vector<RectF> & responseRegionList) const3038 bool FrameNode::InResponseRegionList(const PointF& parentLocalPoint, const std::vector<RectF>& responseRegionList) const
3039 {
3040 for (const auto& rect : responseRegionList) {
3041 if (rect.IsInRegion(parentLocalPoint)) {
3042 return true;
3043 }
3044 }
3045 return false;
3046 }
3047
MouseTest(const PointF & globalPoint,const PointF & parentLocalPoint,MouseTestResult & onMouseResult,MouseTestResult & onHoverResult,RefPtr<FrameNode> & hoverNode)3048 HitTestResult FrameNode::MouseTest(const PointF& globalPoint, const PointF& parentLocalPoint,
3049 MouseTestResult& onMouseResult, MouseTestResult& onHoverResult, RefPtr<FrameNode>& hoverNode)
3050 {
3051 // unuseable function. do nothing.
3052 return HitTestResult::BUBBLING;
3053 }
3054
CheckChildHitTestReslut(HitTestResult childHitResult,const RefPtr<OHOS::Ace::NG::FrameNode> & child,bool & preventBubbling,bool & consumed,bool isExclusiveEventForChild)3055 bool CheckChildHitTestReslut(HitTestResult childHitResult, const RefPtr<OHOS::Ace::NG::FrameNode>& child,
3056 bool& preventBubbling, bool& consumed, bool isExclusiveEventForChild)
3057 {
3058 consumed = false;
3059 if (childHitResult == HitTestResult::STOP_BUBBLING) {
3060 preventBubbling = true;
3061 consumed = true;
3062 return ((child->GetHitTestMode() == HitTestMode::HTMBLOCK) ||
3063 (child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
3064 (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ||
3065 ((child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT) && isExclusiveEventForChild));
3066 } else if (childHitResult == HitTestResult::BUBBLING) {
3067 consumed = true;
3068 return ((child->GetHitTestMode() == HitTestMode::HTMDEFAULT) ||
3069 (child->GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ||
3070 ((child->GetHitTestMode() != HitTestMode::HTMTRANSPARENT) && isExclusiveEventForChild));
3071 }
3072 return false;
3073 }
3074
3075
AxisTest(const PointF & globalPoint,const PointF & parentLocalPoint,const PointF & parentRevertPoint,TouchRestrict & touchRestrict,AxisTestResult & axisResult)3076 HitTestResult FrameNode::AxisTest(const PointF& globalPoint, const PointF& parentLocalPoint,
3077 const PointF& parentRevertPoint, TouchRestrict& touchRestrict, AxisTestResult& axisResult)
3078 {
3079 if (!isActive_ || !eventHub_->IsEnabled()) {
3080 TAG_LOGW(AceLogTag::ACE_UIEVENT, "%{public}s is inActive, need't do touch test", GetTag().c_str());
3081 return HitTestResult::OUT_OF_REGION;
3082 }
3083 {
3084 ACE_DEBUG_SCOPED_TRACE("FrameNode::IsOutOfTouchTestRegion");
3085 if (IsOutOfTouchTestRegion(parentRevertPoint, touchRestrict.touchEvent)) {
3086 return HitTestResult::OUT_OF_REGION;
3087 }
3088 }
3089 HitTestResult testResult = HitTestResult::OUT_OF_REGION;
3090 bool preventBubbling = false;
3091 AxisTestResult newComingTargets;
3092 auto localPoint = parentLocalPoint - renderContext_->GetPaintRectWithTransform().GetOffset();
3093 renderContext_->GetPointWithTransform(localPoint);
3094 auto revertPoint = parentRevertPoint;
3095 MapPointTo(revertPoint, GetOrRefreshRevertMatrixFromCache());
3096 auto subRevertPoint = revertPoint - renderContext_->GetPaintRectWithoutTransform().GetOffset();
3097 bool consumed = false;
3098 for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
3099 if (GetHitTestMode() == HitTestMode::HTMBLOCK) {
3100 break;
3101 }
3102 const auto& child = iter->Upgrade();
3103 if (!child) {
3104 continue;
3105 }
3106 auto childHitResult = child->AxisTest(globalPoint, localPoint, subRevertPoint, touchRestrict, newComingTargets);
3107 if (CheckChildHitTestReslut(childHitResult, child, preventBubbling, consumed, IsExclusiveEventForChild())) {
3108 break;
3109 }
3110 }
3111 CollectSelfAxisResult(
3112 globalPoint, localPoint, consumed, revertPoint, axisResult, preventBubbling, testResult, touchRestrict);
3113
3114 axisResult.splice(axisResult.end(), std::move(newComingTargets));
3115 if (!consumed) {
3116 return testResult;
3117 }
3118 if (testResult == HitTestResult::OUT_OF_REGION && preventBubbling) {
3119 return HitTestResult::STOP_BUBBLING;
3120 } else {
3121 return (GetHitTestMode() == HitTestMode::HTMTRANSPARENT_SELF) ? HitTestResult::SELF_TRANSPARENT
3122 : HitTestResult::BUBBLING;
3123 }
3124 return testResult;
3125 }
3126
CollectSelfAxisResult(const PointF & globalPoint,const PointF & localPoint,bool & consumed,const PointF & parentRevertPoint,AxisTestResult & axisResult,bool & preventBubbling,HitTestResult & testResult,TouchRestrict & touchRestrict)3127 void FrameNode::CollectSelfAxisResult(const PointF& globalPoint, const PointF& localPoint, bool& consumed,
3128 const PointF& parentRevertPoint, AxisTestResult& axisResult, bool& preventBubbling, HitTestResult& testResult,
3129 TouchRestrict& touchRestrict)
3130 {
3131 if (consumed) {
3132 testResult = preventBubbling ? HitTestResult::STOP_BUBBLING : HitTestResult::BUBBLING;
3133 consumed = false;
3134 } else if (GetHitTestMode() == HitTestMode::HTMBLOCK) {
3135 testResult = HitTestResult::STOP_BUBBLING;
3136 }
3137 auto origRect = renderContext_->GetPaintRectWithoutTransform();
3138 auto resRegionList = GetResponseRegionList(origRect, static_cast<int32_t>(touchRestrict.touchEvent.sourceType));
3139 if (SystemProperties::GetDebugEnabled()) {
3140 TAG_LOGD(AceLogTag::ACE_UIEVENT, "AxisTest: point is %{public}s in %{public}s, depth: %{public}d",
3141 parentRevertPoint.ToString().c_str(), GetTag().c_str(), GetDepth());
3142 for (const auto& rect : resRegionList) {
3143 TAG_LOGD(AceLogTag::ACE_UIEVENT, "AxisTest: resRegionList is %{public}s, point is %{public}s",
3144 rect.ToString().c_str(), parentRevertPoint.ToString().c_str());
3145 }
3146 }
3147 if (preventBubbling) {
3148 return;
3149 }
3150 if (GetHitTestMode() == HitTestMode::HTMNONE) {
3151 return;
3152 }
3153 if (InResponseRegionList(parentRevertPoint, resRegionList)) {
3154 consumed = true;
3155 auto inputHub = eventHub_->GetInputEventHub();
3156 if (inputHub) {
3157 const auto coordinateOffset = globalPoint - localPoint;
3158 inputHub->ProcessAxisTestHit(coordinateOffset, axisResult);
3159 }
3160 }
3161 }
3162
AnimateHoverEffect(bool isHovered) const3163 void FrameNode::AnimateHoverEffect(bool isHovered) const
3164 {
3165 auto renderContext = GetRenderContext();
3166 if (!renderContext) {
3167 return;
3168 }
3169 HoverEffectType animationType = HoverEffectType::UNKNOWN;
3170 auto inputEventHub = eventHub_->GetInputEventHub();
3171 if (inputEventHub) {
3172 animationType = inputEventHub->GetHoverEffect();
3173 if (animationType == HoverEffectType::UNKNOWN || animationType == HoverEffectType::AUTO) {
3174 animationType = inputEventHub->GetHoverEffectAuto();
3175 }
3176 }
3177 if (animationType == HoverEffectType::SCALE) {
3178 renderContext->AnimateHoverEffectScale(isHovered);
3179 } else if (animationType == HoverEffectType::BOARD) {
3180 renderContext->AnimateHoverEffectBoard(isHovered);
3181 }
3182 }
3183
GetOrCreateFocusHub() const3184 RefPtr<FocusHub> FrameNode::GetOrCreateFocusHub() const
3185 {
3186 if (!pattern_) {
3187 return eventHub_->GetOrCreateFocusHub();
3188 }
3189 auto focusPattern = pattern_->GetFocusPattern();
3190 return eventHub_->GetOrCreateFocusHub(focusPattern);
3191 }
3192
OnWindowShow()3193 void FrameNode::OnWindowShow()
3194 {
3195 pattern_->OnWindowShow();
3196 }
3197
OnWindowHide()3198 void FrameNode::OnWindowHide()
3199 {
3200 pattern_->OnWindowHide();
3201 }
3202
OnWindowFocused()3203 void FrameNode::OnWindowFocused()
3204 {
3205 if (renderContext_) {
3206 renderContext_->UpdateWindowFocusState(true);
3207 }
3208 pattern_->OnWindowFocused();
3209 }
3210
OnWindowUnfocused()3211 void FrameNode::OnWindowUnfocused()
3212 {
3213 if (renderContext_) {
3214 renderContext_->UpdateWindowFocusState(false);
3215 }
3216 pattern_->OnWindowUnfocused();
3217 }
3218
ContextPositionConvertToPX(const RefPtr<RenderContext> & context,const SizeF & percentReference)3219 std::pair<float, float> FrameNode::ContextPositionConvertToPX(
3220 const RefPtr<RenderContext>& context, const SizeF& percentReference)
3221 {
3222 std::pair<float, float> position;
3223 CHECK_NULL_RETURN(context, position);
3224 auto scaleProperty = ScaleProperty::CreateScaleProperty();
3225 position.first =
3226 ConvertToPx(context->GetPositionProperty()->GetPosition()->GetX(), scaleProperty, percentReference.Width())
3227 .value_or(0.0);
3228 position.second =
3229 ConvertToPx(context->GetPositionProperty()->GetPosition()->GetY(), scaleProperty, percentReference.Height())
3230 .value_or(0.0);
3231 return position;
3232 }
3233
OnPixelRoundFinish(const SizeF & pixelGridRoundSize)3234 void FrameNode::OnPixelRoundFinish(const SizeF& pixelGridRoundSize)
3235 {
3236 CHECK_NULL_VOID(pattern_);
3237 pattern_->OnPixelRoundFinish(pixelGridRoundSize);
3238 }
3239
OnWindowSizeChanged(int32_t width,int32_t height,WindowSizeChangeReason type)3240 void FrameNode::OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type)
3241 {
3242 pattern_->OnWindowSizeChanged(width, height, type);
3243 }
3244
3245 /* @deprecated This func will be deleted, please use GetTransformRelativeOffset() instead. */
GetOffsetRelativeToWindow() const3246 OffsetF FrameNode::GetOffsetRelativeToWindow() const
3247 {
3248 auto offset = geometryNode_->GetFrameOffset();
3249 auto parent = GetAncestorNodeOfFrame(true);
3250 if (renderContext_ && renderContext_->GetPositionProperty()) {
3251 if (renderContext_->GetPositionProperty()->HasPosition()) {
3252 auto renderPosition =
3253 ContextPositionConvertToPX(renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
3254 offset.SetX(static_cast<float>(renderPosition.first));
3255 offset.SetY(static_cast<float>(renderPosition.second));
3256 }
3257 }
3258 while (parent) {
3259 auto parentRenderContext = parent->GetRenderContext();
3260 if (parentRenderContext && parentRenderContext->GetPositionProperty()) {
3261 if (parentRenderContext->GetPositionProperty()->HasPosition()) {
3262 auto parentLayoutProperty = parent->GetLayoutProperty();
3263 CHECK_NULL_RETURN(parentLayoutProperty, offset);
3264 auto parentRenderContextPosition = ContextPositionConvertToPX(
3265 parentRenderContext, parentLayoutProperty->GetLayoutConstraint()->percentReference);
3266 offset.AddX(static_cast<float>(parentRenderContextPosition.first));
3267 offset.AddY(static_cast<float>(parentRenderContextPosition.second));
3268 parent = parent->GetAncestorNodeOfFrame(true);
3269 continue;
3270 }
3271 }
3272 if (parentRenderContext) {
3273 offset += parentRenderContext->GetPaintRectWithoutTransform().GetOffset();
3274 }
3275 parent = parent->GetAncestorNodeOfFrame(true);
3276 }
3277
3278 return offset;
3279 }
3280
GetPositionToScreen()3281 OffsetF FrameNode::GetPositionToScreen()
3282 {
3283 auto offsetCurrent = GetOffsetRelativeToWindow();
3284 auto pipelineContext = GetContext();
3285 CHECK_NULL_RETURN(pipelineContext, OffsetF());
3286 auto windowOffset = pipelineContext->GetCurrentWindowRect().GetOffset();
3287 OffsetF offset(windowOffset.GetX() + offsetCurrent.GetX(), windowOffset.GetY() + offsetCurrent.GetY());
3288 return offset;
3289 }
3290
GetPositionToParentWithTransform() const3291 OffsetF FrameNode::GetPositionToParentWithTransform() const
3292 {
3293 auto context = GetRenderContext();
3294 CHECK_NULL_RETURN(context, OffsetF());
3295 auto offset = context->GetPaintRectWithoutTransform().GetOffset();
3296 PointF pointTmp(offset.GetX(), offset.GetY());
3297 context->GetPointTransformRotate(pointTmp);
3298 offset.SetX(pointTmp.GetX());
3299 offset.SetY(pointTmp.GetY());
3300 return offset;
3301 }
3302
GetPositionToScreenWithTransform()3303 OffsetF FrameNode::GetPositionToScreenWithTransform()
3304 {
3305 auto pipelineContext = GetContext();
3306 CHECK_NULL_RETURN(pipelineContext, OffsetF());
3307 auto windowOffset = pipelineContext->GetCurrentWindowRect().GetOffset();
3308 OffsetF nodeOffset = GetPositionToWindowWithTransform();
3309 OffsetF offset(windowOffset.GetX() + nodeOffset.GetX(), windowOffset.GetY() + nodeOffset.GetY());
3310 return offset;
3311 }
3312
GetPositionToWindowWithTransform(bool fromBottom) const3313 OffsetF FrameNode::GetPositionToWindowWithTransform(bool fromBottom) const
3314 {
3315 auto context = GetRenderContext();
3316 CHECK_NULL_RETURN(context, OffsetF());
3317 auto rect = context->GetPaintRectWithoutTransform();
3318 OffsetF offset;
3319 if (!fromBottom) {
3320 offset = rect.GetOffset();
3321 } else {
3322 OffsetF offsetBottom(rect.GetX() + rect.Width(), rect.GetY() + rect.Height());
3323 offset = offsetBottom;
3324 }
3325 PointF pointNode(offset.GetX(), offset.GetY());
3326 context->GetPointTransformRotate(pointNode);
3327 auto parent = GetAncestorNodeOfFrame(true);
3328 while (parent) {
3329 auto parentRenderContext = parent->GetRenderContext();
3330 offset = parentRenderContext->GetPaintRectWithoutTransform().GetOffset();
3331 PointF pointTmp(offset.GetX() + pointNode.GetX(), offset.GetY() + pointNode.GetY());
3332 parentRenderContext->GetPointTransformRotate(pointTmp);
3333 pointNode.SetX(pointTmp.GetX());
3334 pointNode.SetY(pointTmp.GetY());
3335 parent = parent->GetAncestorNodeOfFrame(true);
3336 }
3337 offset.SetX(pointNode.GetX());
3338 offset.SetY(pointNode.GetY());
3339 return offset;
3340 }
3341
GetTransformScaleRelativeToWindow() const3342 VectorF FrameNode::GetTransformScaleRelativeToWindow() const
3343 {
3344 VectorF finalScale {1.0f, 1.0f};
3345 auto context = GetRenderContext();
3346 if (context) {
3347 auto scale = GetTransformScale();
3348 finalScale.x = scale.x;
3349 finalScale.y = scale.y;
3350 }
3351
3352 auto parent = GetAncestorNodeOfFrame(true);
3353 while (parent) {
3354 auto contextParent = parent->GetRenderContext();
3355 if (contextParent) {
3356 auto scale = parent->GetTransformScale();
3357 finalScale.x *= scale.x;
3358 finalScale.y *= scale.y;
3359 }
3360 parent = parent->GetAncestorNodeOfFrame(true);
3361 }
3362 return finalScale;
3363 }
3364
GetTransformRectRelativeToWindow(bool checkBoundary) const3365 RectF FrameNode::GetTransformRectRelativeToWindow(bool checkBoundary) const
3366 {
3367 auto context = GetRenderContext();
3368 CHECK_NULL_RETURN(context, RectF());
3369 RectF rect = context->GetPaintRectWithTransform();
3370 auto parent = GetAncestorNodeOfFrame(true);
3371 while (parent) {
3372 if (checkBoundary && IsWindowBoundary()) {
3373 break; // exclude windowscene
3374 }
3375 rect = ApplyFrameNodeTranformToRect(rect, parent);
3376 parent = parent->GetAncestorNodeOfFrame(true);
3377 }
3378 return rect;
3379 }
3380
GetTransformRelativeOffset() const3381 OffsetF FrameNode::GetTransformRelativeOffset() const
3382 {
3383 auto context = GetRenderContext();
3384 CHECK_NULL_RETURN(context, OffsetF());
3385 auto offset = context->GetPaintRectWithTransform().GetOffset();
3386 auto parent = GetAncestorNodeOfFrame(true);
3387
3388 while (parent) {
3389 auto parentRenderContext = parent->GetRenderContext();
3390 offset += parentRenderContext->GetPaintRectWithTransform().GetOffset();
3391 parent = parent->GetAncestorNodeOfFrame(true);
3392 }
3393
3394 return offset;
3395 }
3396
GetPaintRectOffset(bool excludeSelf,bool checkBoundary) const3397 OffsetF FrameNode::GetPaintRectOffset(bool excludeSelf, bool checkBoundary) const
3398 {
3399 auto context = GetRenderContext();
3400 CHECK_NULL_RETURN(context, OffsetF());
3401 OffsetF offset = excludeSelf ? OffsetF() : context->GetPaintRectWithTransform().GetOffset();
3402 auto parent = GetAncestorNodeOfFrame(checkBoundary);
3403 while (parent) {
3404 if (!checkBoundary && parent->CheckTopWindowBoundary()) {
3405 break;
3406 }
3407 auto renderContext = parent->GetRenderContext();
3408 CHECK_NULL_RETURN(renderContext, OffsetF());
3409 offset += renderContext->GetPaintRectWithTransform().GetOffset();
3410 parent = parent->GetAncestorNodeOfFrame(checkBoundary);
3411 }
3412 return offset;
3413 }
3414
GetPaintRectOffsetNG(bool excludeSelf,bool checkBoundary) const3415 OffsetF FrameNode::GetPaintRectOffsetNG(bool excludeSelf, bool checkBoundary) const
3416 {
3417 auto context = GetRenderContext();
3418 CHECK_NULL_RETURN(context, OffsetF());
3419 OffsetF offset = excludeSelf ? OffsetF() : context->GetPaintRectWithoutTransform().GetOffset();
3420 Point point = Matrix4::Invert(context->GetRevertMatrix()) * Point(offset.GetX(), offset.GetY());
3421 auto parent = GetAncestorNodeOfFrame(checkBoundary);
3422 while (parent) {
3423 if (!checkBoundary && parent->CheckTopWindowBoundary()) {
3424 break;
3425 }
3426 auto renderContext = parent->GetRenderContext();
3427 CHECK_NULL_RETURN(renderContext, OffsetF());
3428 auto parentOffset = renderContext->GetPaintRectWithoutTransform().GetOffset();
3429 point = point + Offset(parentOffset.GetX(), parentOffset.GetY());
3430 auto parentMatrix = Matrix4::Invert(renderContext->GetRevertMatrix());
3431 point = parentMatrix * point;
3432 parent = parent->GetAncestorNodeOfFrame(checkBoundary);
3433 }
3434 return OffsetF(point.GetX(), point.GetY());
3435 }
3436
GetRectPoints(SizeF & frameSize)3437 std::vector<Point> GetRectPoints(SizeF& frameSize)
3438 {
3439 std::vector<Point> pointList;
3440 pointList.push_back(Point(0, 0));
3441 pointList.push_back(Point(frameSize.Width(), 0));
3442 pointList.push_back(Point(0, frameSize.Height()));
3443 pointList.push_back(Point(frameSize.Width(), frameSize.Height()));
3444 return pointList;
3445 }
3446
GetBoundingBox(std::vector<Point> & pointList)3447 RectF GetBoundingBox(std::vector<Point>& pointList)
3448 {
3449 Point pMax = pointList[0];
3450 Point pMin = pointList[0];
3451
3452 for (auto &point: pointList) {
3453 if (point.GetX() > pMax.GetX()) {
3454 pMax.SetX(point.GetX());
3455 }
3456 if (point.GetX() < pMin.GetX()) {
3457 pMin.SetX(point.GetX());
3458 }
3459 if (point.GetY() > pMax.GetY()) {
3460 pMax.SetY(point.GetY());
3461 }
3462 if (point.GetY() < pMin.GetY()) {
3463 pMin.SetY(point.GetY());
3464 }
3465 }
3466 return RectF(pMin.GetX(), pMin.GetY(), pMax.GetX() - pMin.GetX(), pMax.GetY() - pMin.GetY());
3467 }
3468
GetRectPointToParentWithTransform(std::vector<Point> & pointList,const RefPtr<FrameNode> & parent) const3469 bool FrameNode::GetRectPointToParentWithTransform(std::vector<Point>& pointList, const RefPtr<FrameNode>& parent) const
3470 {
3471 auto renderContext = parent->GetRenderContext();
3472 CHECK_NULL_RETURN(renderContext, false);
3473 auto parentOffset = renderContext->GetPaintRectWithoutTransform().GetOffset();
3474 auto parentMatrix = Matrix4::Invert(renderContext->GetRevertMatrix());
3475 for (auto& point: pointList) {
3476 point = point + Offset(parentOffset.GetX(), parentOffset.GetY());
3477 point = parentMatrix * point;
3478 }
3479 return true;
3480 }
3481
GetPaintRectToWindowWithTransform()3482 RectF FrameNode::GetPaintRectToWindowWithTransform()
3483 {
3484 auto context = GetRenderContext();
3485 CHECK_NULL_RETURN(context, RectF());
3486 auto geometryNode = GetGeometryNode();
3487 CHECK_NULL_RETURN(geometryNode, RectF());
3488 auto frameSize = geometryNode->GetFrameSize();
3489 auto pointList = GetRectPoints(frameSize);
3490 GetRectPointToParentWithTransform(pointList, Claim(this));
3491 auto parent = GetAncestorNodeOfFrame(true);
3492 while (parent) {
3493 if (GetRectPointToParentWithTransform(pointList, parent)) {
3494 parent = parent->GetAncestorNodeOfFrame(true);
3495 } else {
3496 return RectF();
3497 }
3498 }
3499 return GetBoundingBox(pointList);
3500 }
3501
GetPaintRectCenter(bool checkWindowBoundary) const3502 OffsetF FrameNode::GetPaintRectCenter(bool checkWindowBoundary) const
3503 {
3504 auto context = GetRenderContext();
3505 CHECK_NULL_RETURN(context, OffsetF());
3506 auto paintRect = context->GetPaintRectWithoutTransform();
3507 auto offset = paintRect.GetOffset();
3508 PointF pointNode(offset.GetX() + paintRect.Width() / 2.0f, offset.GetY() + paintRect.Height() / 2.0f);
3509 context->GetPointTransformRotate(pointNode);
3510 auto parent = GetAncestorNodeOfFrame(false);
3511 while (parent) {
3512 if (checkWindowBoundary && parent->IsWindowBoundary()) {
3513 break;
3514 }
3515 auto renderContext = parent->GetRenderContext();
3516 CHECK_NULL_RETURN(renderContext, OffsetF());
3517 offset = renderContext->GetPaintRectWithoutTransform().GetOffset();
3518 pointNode.SetX(offset.GetX() + pointNode.GetX());
3519 pointNode.SetY(offset.GetY() + pointNode.GetY());
3520 renderContext->GetPointTransformRotate(pointNode);
3521 parent = parent->GetAncestorNodeOfFrame(false);
3522 }
3523 return OffsetF(pointNode.GetX(), pointNode.GetY());
3524 }
3525
GetParentGlobalOffsetDuringLayout() const3526 OffsetF FrameNode::GetParentGlobalOffsetDuringLayout() const
3527 {
3528 OffsetF offset {};
3529 auto parent = GetAncestorNodeOfFrame(true);
3530 while (parent) {
3531 offset += parent->geometryNode_->GetFrameOffset();
3532 parent = parent->GetAncestorNodeOfFrame(true);
3533 }
3534 return offset;
3535 }
3536
GetPaintRectGlobalOffsetWithTranslate(bool excludeSelf,bool checkBoundary) const3537 std::pair<OffsetF, bool> FrameNode::GetPaintRectGlobalOffsetWithTranslate(bool excludeSelf, bool checkBoundary) const
3538 {
3539 bool error = false;
3540 auto context = GetRenderContext();
3541 CHECK_NULL_RETURN(context, std::make_pair(OffsetF(), error));
3542 OffsetF offset = excludeSelf ? OffsetF() : context->GetPaintRectWithTranslate().first.GetOffset();
3543 auto parent = GetAncestorNodeOfFrame(checkBoundary);
3544 while (parent) {
3545 auto renderContext = parent->GetRenderContext();
3546 CHECK_NULL_RETURN(renderContext, std::make_pair(OffsetF(), error));
3547 auto [rect, err] = renderContext->GetPaintRectWithTranslate();
3548 error = error || err;
3549 CHECK_NULL_RETURN(rect.IsValid(), std::make_pair(offset + parent->GetPaintRectOffset(), error));
3550 offset += rect.GetOffset();
3551 parent = parent->GetAncestorNodeOfFrame(checkBoundary);
3552 }
3553 return std::make_pair(offset, error);
3554 }
3555
GetPaintRectOffsetToPage() const3556 OffsetF FrameNode::GetPaintRectOffsetToPage() const
3557 {
3558 auto context = GetRenderContext();
3559 CHECK_NULL_RETURN(context, OffsetF());
3560 OffsetF offset = context->GetPaintRectWithTransform().GetOffset();
3561 auto parent = GetAncestorNodeOfFrame(true);
3562 while (parent && parent->GetTag() != V2::PAGE_ETS_TAG) {
3563 auto renderContext = parent->GetRenderContext();
3564 CHECK_NULL_RETURN(renderContext, OffsetF());
3565 offset += renderContext->GetPaintRectWithTransform().GetOffset();
3566 parent = parent->GetAncestorNodeOfFrame(true);
3567 }
3568 return (parent && parent->GetTag() == V2::PAGE_ETS_TAG) ? offset : OffsetF();
3569 }
3570
GetViewPort(bool checkBoundary) const3571 std::optional<RectF> FrameNode::GetViewPort(bool checkBoundary) const
3572 {
3573 if (viewPort_.has_value()) {
3574 return viewPort_;
3575 }
3576 auto parent = GetAncestorNodeOfFrame(checkBoundary);
3577 while (parent && parent->GetTag() != V2::PAGE_ETS_TAG) {
3578 auto parentViewPort = parent->GetSelfViewPort();
3579 if (parentViewPort.has_value()) {
3580 return parentViewPort;
3581 }
3582 parent = parent->GetAncestorNodeOfFrame(checkBoundary);
3583 }
3584 return std::nullopt;
3585 }
3586
OnNotifyMemoryLevel(int32_t level)3587 void FrameNode::OnNotifyMemoryLevel(int32_t level)
3588 {
3589 pattern_->OnNotifyMemoryLevel(level);
3590 }
3591
GetAllDepthChildrenCount()3592 int32_t FrameNode::GetAllDepthChildrenCount()
3593 {
3594 int32_t result = 0;
3595 std::list<RefPtr<FrameNode>> children;
3596 children.emplace_back(Claim(this));
3597 while (!children.empty()) {
3598 auto& node = children.front();
3599 if (!node->IsInternal()) {
3600 result++;
3601 node->GenerateOneDepthVisibleFrame(children);
3602 }
3603 children.pop_front();
3604 }
3605 return result;
3606 }
3607
OnAccessibilityEvent(AccessibilityEventType eventType,WindowsContentChangeTypes windowsContentChangeType) const3608 void FrameNode::OnAccessibilityEvent(
3609 AccessibilityEventType eventType, WindowsContentChangeTypes windowsContentChangeType) const
3610 {
3611 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
3612 AccessibilityEvent event;
3613 event.type = eventType;
3614 event.windowContentChangeTypes = windowsContentChangeType;
3615 event.nodeId = GetAccessibilityId();
3616 auto pipeline = GetContext();
3617 CHECK_NULL_VOID(pipeline);
3618 pipeline->SendEventToAccessibility(event);
3619 }
3620 }
3621
OnAccessibilityEventForVirtualNode(AccessibilityEventType eventType,int64_t accessibilityId)3622 void FrameNode::OnAccessibilityEventForVirtualNode(AccessibilityEventType eventType, int64_t accessibilityId)
3623 {
3624 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
3625 AccessibilityEvent event;
3626 event.type = eventType;
3627 event.windowContentChangeTypes = WindowsContentChangeTypes::CONTENT_CHANGE_TYPE_INVALID;
3628 event.nodeId = accessibilityId;
3629 auto pipeline = GetContext();
3630 CHECK_NULL_VOID(pipeline);
3631 pipeline->SendEventToAccessibility(event);
3632 }
3633 }
3634
OnAccessibilityEvent(AccessibilityEventType eventType,std::string beforeText,std::string latestContent)3635 void FrameNode::OnAccessibilityEvent(
3636 AccessibilityEventType eventType, std::string beforeText, std::string latestContent)
3637 {
3638 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
3639 AccessibilityEvent event;
3640 event.type = eventType;
3641 event.nodeId = GetAccessibilityId();
3642 event.beforeText = beforeText;
3643 event.latestContent = latestContent;
3644 auto pipeline = GetContext();
3645 CHECK_NULL_VOID(pipeline);
3646 pipeline->SendEventToAccessibilityWithNode(event, Claim(this));
3647 }
3648 }
3649
OnAccessibilityEvent(AccessibilityEventType eventType,int64_t stackNodeId,WindowsContentChangeTypes windowsContentChangeType)3650 void FrameNode::OnAccessibilityEvent(
3651 AccessibilityEventType eventType, int64_t stackNodeId, WindowsContentChangeTypes windowsContentChangeType)
3652 {
3653 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
3654 AccessibilityEvent event;
3655 event.type = eventType;
3656 event.windowContentChangeTypes = windowsContentChangeType;
3657 event.nodeId = GetAccessibilityId();
3658 event.stackNodeId = stackNodeId;
3659 auto pipeline = GetContext();
3660 CHECK_NULL_VOID(pipeline);
3661 pipeline->SendEventToAccessibility(event);
3662 }
3663 }
3664
OnAccessibilityEvent(AccessibilityEventType eventType,std::string textAnnouncedForAccessibility)3665 void FrameNode::OnAccessibilityEvent(
3666 AccessibilityEventType eventType, std::string textAnnouncedForAccessibility)
3667 {
3668 if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
3669 if (eventType != AccessibilityEventType::ANNOUNCE_FOR_ACCESSIBILITY) {
3670 return;
3671 }
3672 AccessibilityEvent event;
3673 event.type = eventType;
3674 event.nodeId = GetAccessibilityId();
3675 event.textAnnouncedForAccessibility = textAnnouncedForAccessibility;
3676 auto pipeline = GetContext();
3677 CHECK_NULL_VOID(pipeline);
3678 pipeline->SendEventToAccessibilityWithNode(event, Claim(this));
3679 }
3680 }
3681
OnRecycle()3682 void FrameNode::OnRecycle()
3683 {
3684 for (const auto& destroyCallback : destroyCallbacks_) {
3685 destroyCallback();
3686 }
3687 for (const auto& destroyCallback : destroyCallbacksMap_) {
3688 if (destroyCallback.second) {
3689 destroyCallback.second();
3690 }
3691 }
3692 layoutProperty_->ResetGeometryTransition();
3693 pattern_->OnRecycle();
3694 UINode::OnRecycle();
3695 }
3696
OnReuse()3697 void FrameNode::OnReuse()
3698 {
3699 pattern_->OnReuse();
3700 UINode::OnReuse();
3701 if (SystemProperties::GetDeveloperModeOn()) {
3702 PaintDebugBoundary(SystemProperties::GetDebugBoundaryEnabled());
3703 }
3704 }
3705
MarkRemoving()3706 bool FrameNode::MarkRemoving()
3707 {
3708 bool pendingRemove = false;
3709 if (!layoutProperty_ || !geometryNode_) {
3710 return pendingRemove;
3711 }
3712
3713 isRemoving_ = true;
3714
3715 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
3716 if (geometryTransition != nullptr) {
3717 geometryTransition->Build(WeakClaim(this), false);
3718 pendingRemove = true;
3719 }
3720
3721 const auto children = GetChildren();
3722 for (const auto& child : children) {
3723 pendingRemove = child->MarkRemoving() || pendingRemove;
3724 }
3725 return pendingRemove;
3726 }
3727
AddHotZoneRect(const DimensionRect & hotZoneRect) const3728 void FrameNode::AddHotZoneRect(const DimensionRect& hotZoneRect) const
3729 {
3730 auto gestureHub = GetOrCreateGestureEventHub();
3731 gestureHub->AddResponseRect(hotZoneRect);
3732 }
3733
RemoveLastHotZoneRect() const3734 void FrameNode::RemoveLastHotZoneRect() const
3735 {
3736 auto gestureHub = GetOrCreateGestureEventHub();
3737 gestureHub->RemoveLastResponseRect();
3738 }
3739
OnRemoveFromParent(bool allowTransition)3740 bool FrameNode::OnRemoveFromParent(bool allowTransition)
3741 {
3742 // kick out transition animation if needed, wont re-entry if already detached.
3743 DetachFromMainTree(!allowTransition);
3744 auto context = GetRenderContext();
3745 CHECK_NULL_RETURN(context, false);
3746 if (!allowTransition || RemoveImmediately()) {
3747 // directly remove, reset parent and depth
3748 ResetParent();
3749 return true;
3750 }
3751 // delayed remove, will move self into disappearing children
3752 return false;
3753 }
3754
FindChildByPosition(float x,float y)3755 RefPtr<FrameNode> FrameNode::FindChildByPosition(float x, float y)
3756 {
3757 std::map<int32_t, RefPtr<FrameNode>> hitFrameNodes;
3758 std::list<RefPtr<FrameNode>> children;
3759 GenerateOneDepthAllFrame(children);
3760 for (const auto& child : children) {
3761 if (!child->IsActive()) {
3762 continue;
3763 }
3764 auto geometryNode = child->GetGeometryNode();
3765 if (!geometryNode) {
3766 continue;
3767 }
3768
3769 auto globalFrameRect = geometryNode->GetFrameRect();
3770 globalFrameRect.SetOffset(child->GetOffsetRelativeToWindow());
3771
3772 if (globalFrameRect.IsInRegion(PointF(x, y))) {
3773 hitFrameNodes.insert(std::make_pair(child->GetDepth(), child));
3774 }
3775 }
3776
3777 if (hitFrameNodes.empty()) {
3778 return nullptr;
3779 }
3780
3781 return hitFrameNodes.rbegin()->second;
3782 }
3783
FindChildByPositionWithoutChildTransform(float x,float y)3784 RefPtr<FrameNode> FrameNode::FindChildByPositionWithoutChildTransform(float x, float y)
3785 {
3786 std::map<int32_t, RefPtr<FrameNode>> hitFrameNodes;
3787 std::list<RefPtr<FrameNode>> children;
3788 GenerateOneDepthAllFrame(children);
3789 auto parentOffset = GetPositionToWindowWithTransform();
3790 for (const auto& child : children) {
3791 if (!child->IsActive()) {
3792 continue;
3793 }
3794 auto geometryNode = child->GetGeometryNode();
3795 if (!geometryNode) {
3796 continue;
3797 }
3798
3799 auto globalFrameRect = geometryNode->GetFrameRect();
3800 auto childOffset = child->GetGeometryNode()->GetFrameOffset();
3801 childOffset += parentOffset;
3802 globalFrameRect.SetOffset(childOffset);
3803
3804 if (globalFrameRect.IsInRegion(PointF(x, y))) {
3805 hitFrameNodes.insert(std::make_pair(child->GetDepth(), child));
3806 }
3807 }
3808
3809 if (hitFrameNodes.empty()) {
3810 return nullptr;
3811 }
3812
3813 return hitFrameNodes.rbegin()->second;
3814 }
3815
GetAnimatablePropertyFloat(const std::string & propertyName) const3816 RefPtr<NodeAnimatablePropertyBase> FrameNode::GetAnimatablePropertyFloat(const std::string& propertyName) const
3817 {
3818 auto iter = nodeAnimatablePropertyMap_.find(propertyName);
3819 if (iter == nodeAnimatablePropertyMap_.end()) {
3820 return nullptr;
3821 }
3822 return iter->second;
3823 }
3824
FindChildByName(const RefPtr<FrameNode> & parentNode,const std::string & nodeName)3825 RefPtr<FrameNode> FrameNode::FindChildByName(const RefPtr<FrameNode>& parentNode, const std::string& nodeName)
3826 {
3827 CHECK_NULL_RETURN(parentNode, nullptr);
3828 const auto& children = parentNode->GetChildren();
3829 for (const auto& child : children) {
3830 auto childFrameNode = AceType::DynamicCast<FrameNode>(child);
3831 if (childFrameNode && childFrameNode->GetInspectorId().value_or("") == nodeName) {
3832 return childFrameNode;
3833 }
3834 auto childFindResult = FindChildByName(childFrameNode, nodeName);
3835 if (childFindResult) {
3836 return childFindResult;
3837 }
3838 }
3839 return nullptr;
3840 }
3841
CreateAnimatablePropertyFloat(const std::string & propertyName,float value,const std::function<void (float)> & onCallbackEvent,const PropertyUnit & propertyType)3842 void FrameNode::CreateAnimatablePropertyFloat(const std::string& propertyName, float value,
3843 const std::function<void(float)>& onCallbackEvent, const PropertyUnit& propertyType)
3844 {
3845 auto context = GetRenderContext();
3846 CHECK_NULL_VOID(context);
3847 auto iter = nodeAnimatablePropertyMap_.find(propertyName);
3848 if (iter != nodeAnimatablePropertyMap_.end()) {
3849 return;
3850 }
3851 auto property = AceType::MakeRefPtr<NodeAnimatablePropertyFloat>(value, std::move(onCallbackEvent));
3852 context->AttachNodeAnimatableProperty(property);
3853 if (propertyType == PropertyUnit::PIXEL_POSITION) {
3854 property->SetPropertyUnit(propertyType);
3855 }
3856 nodeAnimatablePropertyMap_.emplace(propertyName, property);
3857 }
3858
DeleteAnimatablePropertyFloat(const std::string & propertyName)3859 void FrameNode::DeleteAnimatablePropertyFloat(const std::string& propertyName)
3860 {
3861 auto context = GetRenderContext();
3862 CHECK_NULL_VOID(context);
3863 RefPtr<NodeAnimatablePropertyBase> propertyRef = GetAnimatablePropertyFloat(propertyName);
3864 if (propertyRef) {
3865 context->DetachNodeAnimatableProperty(propertyRef);
3866 nodeAnimatablePropertyMap_.erase(propertyName);
3867 }
3868 }
3869
UpdateAnimatablePropertyFloat(const std::string & propertyName,float value)3870 void FrameNode::UpdateAnimatablePropertyFloat(const std::string& propertyName, float value)
3871 {
3872 auto iter = nodeAnimatablePropertyMap_.find(propertyName);
3873 if (iter == nodeAnimatablePropertyMap_.end()) {
3874 return;
3875 }
3876 auto property = AceType::DynamicCast<NodeAnimatablePropertyFloat>(iter->second);
3877 CHECK_NULL_VOID(property);
3878 property->Set(value);
3879 if (AnimationUtils::IsImplicitAnimationOpen()) {
3880 AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_START_ANIMATION);
3881 }
3882 }
3883
CreateAnimatableArithmeticProperty(const std::string & propertyName,RefPtr<CustomAnimatableArithmetic> & value,std::function<void (const RefPtr<CustomAnimatableArithmetic> &)> & onCallbackEvent)3884 void FrameNode::CreateAnimatableArithmeticProperty(const std::string& propertyName,
3885 RefPtr<CustomAnimatableArithmetic>& value,
3886 std::function<void(const RefPtr<CustomAnimatableArithmetic>&)>& onCallbackEvent)
3887 {
3888 auto context = GetRenderContext();
3889 CHECK_NULL_VOID(context);
3890 auto iter = nodeAnimatablePropertyMap_.find(propertyName);
3891 if (iter != nodeAnimatablePropertyMap_.end()) {
3892 return;
3893 }
3894 auto property = AceType::MakeRefPtr<NodeAnimatableArithmeticProperty>(value, std::move(onCallbackEvent));
3895 context->AttachNodeAnimatableProperty(property);
3896 nodeAnimatablePropertyMap_.emplace(propertyName, property);
3897 }
3898
UpdateAnimatableArithmeticProperty(const std::string & propertyName,RefPtr<CustomAnimatableArithmetic> & value)3899 void FrameNode::UpdateAnimatableArithmeticProperty(
3900 const std::string& propertyName, RefPtr<CustomAnimatableArithmetic>& value)
3901 {
3902 auto iter = nodeAnimatablePropertyMap_.find(propertyName);
3903 if (iter == nodeAnimatablePropertyMap_.end()) {
3904 return;
3905 }
3906 auto property = AceType::DynamicCast<NodeAnimatableArithmeticProperty>(iter->second);
3907 CHECK_NULL_VOID(property);
3908 property->Set(value);
3909 }
3910
ProvideRestoreInfo()3911 std::string FrameNode::ProvideRestoreInfo()
3912 {
3913 return pattern_->ProvideRestoreInfo();
3914 }
3915
RemoveImmediately() const3916 bool FrameNode::RemoveImmediately() const
3917 {
3918 auto context = GetRenderContext();
3919 CHECK_NULL_RETURN(context, true);
3920 // has transition out animation, need to wait for animation end
3921 return !context->HasTransitionOutAnimation();
3922 }
3923
GetNodesById(const std::unordered_set<int32_t> & set)3924 std::vector<RefPtr<FrameNode>> FrameNode::GetNodesById(const std::unordered_set<int32_t>& set)
3925 {
3926 std::vector<RefPtr<FrameNode>> nodes;
3927 for (auto nodeId : set) {
3928 auto uiNode = ElementRegister::GetInstance()->GetUINodeById(nodeId);
3929 if (!uiNode) {
3930 continue;
3931 }
3932 auto frameNode = DynamicCast<FrameNode>(uiNode);
3933 if (frameNode) {
3934 nodes.emplace_back(frameNode);
3935 }
3936 }
3937 return nodes;
3938 }
3939
GetNodesPtrById(const std::unordered_set<int32_t> & set)3940 std::vector<FrameNode*> FrameNode::GetNodesPtrById(const std::unordered_set<int32_t>& set)
3941 {
3942 std::vector<FrameNode*> nodes;
3943 for (auto nodeId : set) {
3944 NG::FrameNode* frameNode = ElementRegister::GetInstance()->GetFrameNodePtrById(nodeId);
3945 if (!frameNode) {
3946 continue;
3947 }
3948 nodes.emplace_back(frameNode);
3949 }
3950 return nodes;
3951 }
3952
GetPreviewScaleVal() const3953 double FrameNode::GetPreviewScaleVal() const
3954 {
3955 double scale = 1.0;
3956 auto maxWidth = DragDropManager::GetMaxWidthBaseOnGridSystem(GetContextRefPtr());
3957 auto geometryNode = GetGeometryNode();
3958 CHECK_NULL_RETURN(geometryNode, scale);
3959 auto width = geometryNode->GetFrameRect().Width();
3960 if (GetTag() != V2::WEB_ETS_TAG && width != 0 && width > maxWidth && previewOption_.isScaleEnabled) {
3961 scale = maxWidth / width;
3962 }
3963 return scale;
3964 }
3965
IsPreviewNeedScale() const3966 bool FrameNode::IsPreviewNeedScale() const
3967 {
3968 return GetPreviewScaleVal() < 1.0f;
3969 }
3970
GetNodeExpectedRate()3971 int32_t FrameNode::GetNodeExpectedRate()
3972 {
3973 if (sceneRateMap_.empty()) {
3974 return 0;
3975 }
3976 auto iter = std::max_element(
3977 sceneRateMap_.begin(), sceneRateMap_.end(), [](auto a, auto b) { return a.second < b.second; });
3978 return iter->second;
3979 }
3980
AddFRCSceneInfo(const std::string & scene,float speed,SceneStatus status)3981 void FrameNode::AddFRCSceneInfo(const std::string& scene, float speed, SceneStatus status)
3982 {
3983 if (SystemProperties::GetDebugEnabled()) {
3984 const std::string sceneStatusStrs[] = { "START", "RUNNING", "END" };
3985 LOGD("%{public}s AddFRCSceneInfo scene:%{public}s speed:%{public}f status:%{public}s", GetTag().c_str(),
3986 scene.c_str(), std::abs(speed), sceneStatusStrs[static_cast<int32_t>(status)].c_str());
3987 }
3988
3989 auto renderContext = GetRenderContext();
3990 CHECK_NULL_VOID(renderContext);
3991 auto pipelineContext = GetContext();
3992 CHECK_NULL_VOID(pipelineContext);
3993 auto frameRateManager = pipelineContext->GetFrameRateManager();
3994 CHECK_NULL_VOID(frameRateManager);
3995
3996 auto expectedRate = renderContext->CalcExpectedFrameRate(scene, std::abs(speed));
3997 auto nodeId = GetId();
3998 auto iter = sceneRateMap_.find(scene);
3999 switch (status) {
4000 case SceneStatus::START: {
4001 if (iter == sceneRateMap_.end()) {
4002 if (sceneRateMap_.empty()) {
4003 frameRateManager->AddNodeRate(nodeId);
4004 }
4005 sceneRateMap_.emplace(scene, expectedRate);
4006 frameRateManager->UpdateNodeRate(nodeId, GetNodeExpectedRate());
4007 }
4008 return;
4009 }
4010 case SceneStatus::RUNNING: {
4011 if (iter != sceneRateMap_.end() && iter->second != expectedRate) {
4012 iter->second = expectedRate;
4013 auto nodeExpectedRate = GetNodeExpectedRate();
4014 frameRateManager->UpdateNodeRate(nodeId, nodeExpectedRate);
4015 }
4016 return;
4017 }
4018 case SceneStatus::END: {
4019 if (iter != sceneRateMap_.end()) {
4020 sceneRateMap_.erase(iter);
4021 if (sceneRateMap_.empty()) {
4022 frameRateManager->RemoveNodeRate(nodeId);
4023 } else {
4024 auto nodeExpectedRate = GetNodeExpectedRate();
4025 frameRateManager->UpdateNodeRate(nodeId, nodeExpectedRate);
4026 }
4027 }
4028 return;
4029 }
4030 default:
4031 return;
4032 }
4033 }
4034
GetPercentSensitive()4035 void FrameNode::GetPercentSensitive()
4036 {
4037 auto res = layoutProperty_->GetPercentSensitive();
4038 if (res.first) {
4039 if (layoutAlgorithm_) {
4040 layoutAlgorithm_->SetPercentWidth(true);
4041 }
4042 }
4043 if (res.second) {
4044 if (layoutAlgorithm_) {
4045 layoutAlgorithm_->SetPercentHeight(true);
4046 }
4047 }
4048 }
4049
UpdatePercentSensitive()4050 void FrameNode::UpdatePercentSensitive()
4051 {
4052 bool percentHeight = layoutAlgorithm_ ? layoutAlgorithm_->GetPercentHeight() : true;
4053 bool percentWidth = layoutAlgorithm_ ? layoutAlgorithm_->GetPercentWidth() : true;
4054 auto res = layoutProperty_->UpdatePercentSensitive(percentWidth, percentHeight);
4055 if (res.first) {
4056 auto parent = GetAncestorNodeOfFrame(true);
4057 if (parent && parent->layoutAlgorithm_) {
4058 parent->layoutAlgorithm_->SetPercentWidth(true);
4059 }
4060 }
4061 if (res.second) {
4062 auto parent = GetAncestorNodeOfFrame(true);
4063 if (parent && parent->layoutAlgorithm_) {
4064 parent->layoutAlgorithm_->SetPercentHeight(true);
4065 }
4066 }
4067 }
4068
4069 // This will call child and self measure process.
Measure(const std::optional<LayoutConstraintF> & parentConstraint)4070 void FrameNode::Measure(const std::optional<LayoutConstraintF>& parentConstraint)
4071 {
4072 ACE_LAYOUT_TRACE_BEGIN("Measure[%s][self:%d][parent:%d][key:%s]", GetTag().c_str(), GetId(),
4073 GetAncestorNodeOfFrame(true) ? GetAncestorNodeOfFrame(true)->GetId() : 0, GetInspectorIdValue("").c_str());
4074 ArkUIPerfMonitor::GetInstance().RecordLayoutNode();
4075 isLayoutComplete_ = false;
4076 if (!oldGeometryNode_) {
4077 oldGeometryNode_ = geometryNode_->Clone();
4078 }
4079 pattern_->BeforeCreateLayoutWrapper();
4080 GetLayoutAlgorithm(true);
4081
4082 if (layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE) == VisibleType::GONE) {
4083 layoutAlgorithm_->SetSkipMeasure();
4084 layoutAlgorithm_->SetSkipLayout();
4085 geometryNode_->SetFrameSize(SizeF());
4086 geometryNode_->UpdateMargin(MarginPropertyF());
4087 isLayoutDirtyMarked_ = false;
4088 ACE_LAYOUT_TRACE_END()
4089 return;
4090 }
4091 if (!isActive_) {
4092 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_MEASURE);
4093 }
4094
4095 if (layoutAlgorithm_->SkipMeasure()) {
4096 isLayoutDirtyMarked_ = false;
4097 ACE_LAYOUT_TRACE_END()
4098 return;
4099 }
4100
4101 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
4102 if (geometryTransition != nullptr && geometryTransition->IsRunning(WeakClaim(this))) {
4103 geometryTransition->WillLayout(Claim(this));
4104 }
4105 auto preConstraint = layoutProperty_->GetLayoutConstraint();
4106 auto contentConstraint = layoutProperty_->GetContentLayoutConstraint();
4107 layoutProperty_->BuildGridProperty(Claim(this));
4108
4109 if (layoutProperty_->GetLayoutRect()) {
4110 layoutProperty_->UpdateLayoutConstraintWithLayoutRect();
4111 } else if (parentConstraint) {
4112 ApplyConstraint(*parentConstraint);
4113 } else {
4114 CreateRootConstraint();
4115 }
4116
4117 layoutProperty_->UpdateContentConstraint();
4118 geometryNode_->UpdateMargin(layoutProperty_->CreateMargin());
4119 geometryNode_->UpdatePaddingWithBorder(layoutProperty_->CreatePaddingAndBorder());
4120
4121 isConstraintNotChanged_ = layoutProperty_->ConstraintEqual(preConstraint, contentConstraint);
4122
4123 isLayoutDirtyMarked_ = false;
4124
4125 if (isConstraintNotChanged_) {
4126 if (!CheckNeedForceMeasureAndLayout()) {
4127 ACE_SCOPED_TRACE("SkipMeasure [%s][self:%d]", GetTag().c_str(), GetId());
4128 layoutAlgorithm_->SetSkipMeasure();
4129 ACE_LAYOUT_TRACE_END()
4130 return;
4131 }
4132 } else {
4133 contentConstraintChanges_.UpdateFlags(contentConstraint, layoutProperty_->GetContentLayoutConstraint());
4134 constraintChanges_.UpdateFlags(preConstraint, layoutProperty_->GetLayoutConstraint());
4135 }
4136
4137 GetPercentSensitive();
4138
4139 if (extensionHandler_ && !extensionHandler_->HasDrawModifier()) {
4140 auto extensionLayoutConstraint =
4141 ExtensionLayoutConstraint::Create(GetLayoutProperty()->GetLayoutConstraint().value());
4142 extensionHandler_->SetInnerMeasureImpl([this](const ExtensionLayoutConstraint&) {
4143 auto size = layoutAlgorithm_->MeasureContent(layoutProperty_->CreateContentConstraint(), this);
4144 if (size.has_value()) {
4145 geometryNode_->SetContentSize(size.value());
4146 }
4147 layoutAlgorithm_->Measure(this);
4148 });
4149 extensionHandler_->Measure(extensionLayoutConstraint);
4150 } else {
4151 auto size = layoutAlgorithm_->MeasureContent(layoutProperty_->CreateContentConstraint(), this);
4152 if (size.has_value()) {
4153 geometryNode_->SetContentSize(size.value());
4154 }
4155 layoutAlgorithm_->Measure(this);
4156 }
4157
4158 if (overlayNode_) {
4159 overlayNode_->Measure(layoutProperty_->CreateChildConstraint());
4160 }
4161 UpdatePercentSensitive();
4162 // check aspect radio.
4163 if (pattern_ && pattern_->IsNeedAdjustByAspectRatio() && !layoutProperty_->GetLayoutRect()) {
4164 const auto& magicItemProperty = layoutProperty_->GetMagicItemProperty();
4165 auto aspectRatio = magicItemProperty.GetAspectRatioValue();
4166 // Adjust by aspect ratio, firstly pick height based on width. It means that when width, height and
4167 // aspectRatio are all set, the height is not used.
4168 auto width = geometryNode_->GetFrameSize().Width();
4169 auto height = width / aspectRatio;
4170 geometryNode_->SetFrameSize(SizeF({ width, height }));
4171 }
4172
4173 layoutProperty_->UpdatePropertyChangeFlag(PROPERTY_UPDATE_LAYOUT);
4174 ACE_LAYOUT_TRACE_END()
4175 }
4176
4177 // Called to perform layout children.
Layout()4178 void FrameNode::Layout()
4179 {
4180 ACE_LAYOUT_TRACE_BEGIN("Layout[%s][self:%d][parent:%d][key:%s]", GetTag().c_str(), GetId(),
4181 GetAncestorNodeOfFrame(true) ? GetAncestorNodeOfFrame(true)->GetId() : 0, GetInspectorIdValue("").c_str());
4182 if (layoutProperty_->GetLayoutRect()) {
4183 GetGeometryNode()->SetFrameOffset(layoutProperty_->GetLayoutRect().value().GetOffset());
4184 }
4185 int64_t time = GetSysTimestamp();
4186 OffsetNodeToSafeArea();
4187 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
4188 if (geometryTransition != nullptr) {
4189 if (geometryTransition->IsNodeInAndActive(Claim(this))) {
4190 if (IsRootMeasureNode()) {
4191 UINode::SetGeometryTransitionInRecursive(true);
4192 } else {
4193 SetSkipSyncGeometryNode();
4194 }
4195 }
4196 }
4197 if (CheckNeedLayout(layoutProperty_->GetPropertyChangeFlag())) {
4198 if (!layoutProperty_->GetLayoutConstraint()) {
4199 const auto& parentLayoutConstraint = geometryNode_->GetParentLayoutConstraint();
4200 if (layoutProperty_->GetLayoutRect()) {
4201 layoutProperty_->UpdateLayoutConstraintWithLayoutRect();
4202 } else if (parentLayoutConstraint) {
4203 layoutProperty_->UpdateLayoutConstraint(parentLayoutConstraint.value());
4204 } else {
4205 LayoutConstraintF layoutConstraint;
4206 layoutConstraint.percentReference.SetWidth(PipelineContext::GetCurrentRootWidth());
4207 layoutConstraint.percentReference.SetHeight(PipelineContext::GetCurrentRootHeight());
4208 layoutProperty_->UpdateLayoutConstraint(layoutConstraint);
4209 }
4210 layoutProperty_->UpdateContentConstraint();
4211 }
4212
4213 if (extensionHandler_ && !extensionHandler_->HasDrawModifier()) {
4214 extensionHandler_->SetInnerLayoutImpl(
4215 [this](int32_t, int32_t, int32_t, int32_t) { GetLayoutAlgorithm()->Layout(this); });
4216 const auto& rect = geometryNode_->GetFrameRect();
4217 extensionHandler_->Layout(rect.Width(), rect.Height(), rect.GetX(), rect.GetY());
4218 } else {
4219 GetLayoutAlgorithm()->Layout(this);
4220 }
4221
4222 if (overlayNode_) {
4223 LayoutOverlay();
4224 }
4225 time = GetSysTimestamp() - time;
4226 AddNodeFlexLayouts();
4227 AddNodeLayoutTime(time);
4228 } else {
4229 GetLayoutAlgorithm()->SetSkipLayout();
4230 }
4231
4232 auto pipeline = GetContext();
4233 CHECK_NULL_VOID_LAYOUT_TRACE_END(pipeline);
4234 auto stageManager = pipeline->GetStageManager();
4235 CHECK_NULL_VOID(stageManager);
4236 bool isFocusOnPage = stageManager->CheckPageFocus();
4237 bool needSyncRsNode = false;
4238 DirtySwapConfig config;
4239 bool willSyncGeoProperties = OnLayoutFinish(needSyncRsNode, config);
4240 needSyncRsNode |= AvoidKeyboard(isFocusOnPage);
4241 if (GetIsGeometryTransitionIn()) {
4242 renderContext_->SetFrameWithoutAnimation(renderContext_->GetPaintRectWithoutTransform());
4243 SetIsGeometryTransitionIn(false);
4244 }
4245 // skip wrapping task if node will not sync
4246 CHECK_NULL_VOID_LAYOUT_TRACE_END(willSyncGeoProperties);
4247 auto task = [weak = WeakClaim(this), needSync = needSyncRsNode, dirtyConfig = config]() {
4248 auto frameNode = weak.Upgrade();
4249 CHECK_NULL_VOID(frameNode);
4250 frameNode->SyncGeometryNode(needSync, dirtyConfig);
4251 };
4252 pipeline->AddSyncGeometryNodeTask(task);
4253 if (SelfOrParentExpansive()) {
4254 auto pipeline = GetContext();
4255 CHECK_NULL_VOID_LAYOUT_TRACE_END(pipeline);
4256 auto safeAreaManager = pipeline->GetSafeAreaManager();
4257 CHECK_NULL_VOID_LAYOUT_TRACE_END(safeAreaManager);
4258 safeAreaManager->AddNeedExpandNode(GetHostNode());
4259 }
4260 // if a node has geo transition but not the root node, add task only but not flush
4261 // or add to expand list, self node will be added to expand list in next layout
4262 if (geometryTransition != nullptr && !IsRootMeasureNode()) {
4263 ACE_LAYOUT_TRACE_END()
4264 return;
4265 }
4266 if (geometryTransition != nullptr) {
4267 pipeline->FlushSyncGeometryNodeTasks();
4268 }
4269 ACE_LAYOUT_TRACE_END()
4270 }
4271
SelfExpansive()4272 bool FrameNode::SelfExpansive()
4273 {
4274 auto&& opts = GetLayoutProperty()->GetSafeAreaExpandOpts();
4275 return opts && (opts->Expansive() || opts->switchToNone);
4276 }
4277
SelfExpansiveToKeyboard()4278 bool FrameNode::SelfExpansiveToKeyboard()
4279 {
4280 auto&& opts = GetLayoutProperty()->GetSafeAreaExpandOpts();
4281 return opts && opts->ExpansiveToKeyboard();
4282 }
4283
ParentExpansive()4284 bool FrameNode::ParentExpansive()
4285 {
4286 auto parent = GetAncestorNodeOfFrame(false);
4287 CHECK_NULL_RETURN(parent, false);
4288 auto parentLayoutProperty = parent->GetLayoutProperty();
4289 CHECK_NULL_RETURN(parentLayoutProperty, false);
4290 auto&& parentOpts = parentLayoutProperty->GetSafeAreaExpandOpts();
4291 return parentOpts && parentOpts->Expansive();
4292 }
4293
ProcessSafeAreaPadding()4294 void FrameNode::ProcessSafeAreaPadding()
4295 {
4296 pattern_->ProcessSafeAreaPadding();
4297 }
4298
UpdateFocusState()4299 void FrameNode::UpdateFocusState()
4300 {
4301 auto focusHub = GetFocusHub();
4302 if (focusHub && focusHub->IsCurrentFocus()) {
4303 focusHub->ClearFocusState();
4304 focusHub->PaintFocusState();
4305 }
4306 }
4307
SelfOrParentExpansive()4308 bool FrameNode::SelfOrParentExpansive()
4309 {
4310 return SelfExpansive() || ParentExpansive();
4311 }
4312
ProcessAccessibilityVirtualNode()4313 void FrameNode::ProcessAccessibilityVirtualNode()
4314 {
4315 if (!hasAccessibilityVirtualNode_) {
4316 return;
4317 }
4318 auto accessibilityProperty = GetAccessibilityProperty<AccessibilityProperty>();
4319 auto virtualNode = accessibilityProperty->GetAccessibilityVirtualNode();
4320 auto virtualFrameNode = AceType::DynamicCast<NG::FrameNode>(virtualNode);
4321 if (virtualFrameNode) {
4322 auto constraint = GetLayoutConstraint();
4323 virtualFrameNode->ApplyConstraint(constraint);
4324 ProcessOffscreenNode(virtualFrameNode);
4325 }
4326 }
4327
UpdateAccessibilityNodeRect()4328 void FrameNode::UpdateAccessibilityNodeRect()
4329 {
4330 auto accessibilityProperty = GetAccessibilityProperty<AccessibilityProperty>();
4331 CHECK_NULL_VOID(accessibilityProperty);
4332 auto isFocus = accessibilityProperty->GetAccessibilityFocusState();
4333 if (isFocus && !IsAccessibilityVirtualNode()) {
4334 renderContext_->UpdateAccessibilityRoundRect();
4335 }
4336 }
4337
OnLayoutFinish(bool & needSyncRsNode,DirtySwapConfig & config)4338 bool FrameNode::OnLayoutFinish(bool& needSyncRsNode, DirtySwapConfig& config)
4339 {
4340 auto context = GetContext();
4341 if (isLayoutNode_ && context) {
4342 context->AddLayoutNode(Claim(this));
4343 }
4344 isLayoutComplete_ = true;
4345 const auto& geometryTransition = layoutProperty_->GetGeometryTransition();
4346 bool hasTransition = geometryTransition != nullptr && geometryTransition->IsRunning(WeakClaim(this));
4347 if (!isActive_ && !hasTransition) {
4348 layoutAlgorithm_.Reset();
4349 return false;
4350 }
4351 if (needSkipSyncGeometryNode_ && (!geometryTransition || !geometryTransition->IsNodeInAndActive(Claim(this)))) {
4352 layoutAlgorithm_.Reset();
4353 return false;
4354 }
4355 // update layout size.
4356 bool frameSizeChange = true;
4357 bool frameOffsetChange = true;
4358 bool contentSizeChange = true;
4359 bool contentOffsetChange = true;
4360 if (oldGeometryNode_) {
4361 frameSizeChange = geometryNode_->GetFrameSize() != oldGeometryNode_->GetFrameSize();
4362 frameOffsetChange = geometryNode_->GetFrameOffset() != oldGeometryNode_->GetFrameOffset();
4363 contentSizeChange = geometryNode_->GetContentSize() != oldGeometryNode_->GetContentSize();
4364 contentOffsetChange = geometryNode_->GetContentOffset() != oldGeometryNode_->GetContentOffset();
4365 oldGeometryNode_.Reset();
4366 }
4367
4368 // clean layout flag.
4369 layoutProperty_->CleanDirty();
4370 needSyncRsNode = frameSizeChange || frameOffsetChange ||
4371 (pattern_->GetContextParam().has_value() && contentSizeChange) || HasPositionProp() ||
4372 SelfOrParentExpansive();
4373 if (hasTransition) {
4374 geometryTransition->DidLayout(Claim(this));
4375 if (geometryTransition->IsNodeOutAndActive(WeakClaim(this))) {
4376 isLayoutDirtyMarked_ = true;
4377 }
4378 needSyncRsNode = false;
4379 }
4380 if (GetTag() != V2::PAGE_ETS_TAG) {
4381 renderContext_->SavePaintRect(true, layoutProperty_->GetPixelRound());
4382 if (needSyncRsNode) {
4383 renderContext_->SyncPartialRsProperties();
4384 }
4385 }
4386 config = { .frameSizeChange = frameSizeChange,
4387 .frameOffsetChange = frameOffsetChange,
4388 .contentSizeChange = contentSizeChange,
4389 .contentOffsetChange = contentOffsetChange };
4390 // check if need to paint content.
4391 auto layoutAlgorithmWrapper = DynamicCast<LayoutAlgorithmWrapper>(layoutAlgorithm_);
4392 CHECK_NULL_RETURN(layoutAlgorithmWrapper, false);
4393 config.skipMeasure = layoutAlgorithmWrapper->SkipMeasure();
4394 config.skipLayout = layoutAlgorithmWrapper->SkipLayout();
4395 if (!config.skipMeasure && !config.skipLayout) {
4396 auto pipeline = PipelineContext::GetCurrentContext();
4397 CHECK_NULL_RETURN(pipeline, false);
4398 if (GetInspectorId()) {
4399 pipeline->OnLayoutCompleted(GetInspectorId()->c_str());
4400 }
4401 if (eventHub_ != nullptr) {
4402 eventHub_->FireLayoutNDKCallback(pipeline);
4403 }
4404 }
4405 auto needRerender = pattern_->OnDirtyLayoutWrapperSwap(Claim(this), config);
4406 needRerender =
4407 needRerender || pattern_->OnDirtyLayoutWrapperSwap(Claim(this), config.skipMeasure, config.skipLayout);
4408 if (needRerender || (extensionHandler_ && extensionHandler_->NeedRender()) ||
4409 CheckNeedRender(paintProperty_->GetPropertyChangeFlag())) {
4410 MarkDirtyNode(true, true, PROPERTY_UPDATE_RENDER);
4411 }
4412 layoutAlgorithm_.Reset();
4413 UpdateAccessibilityNodeRect();
4414 ProcessAccessibilityVirtualNode();
4415 auto pipeline = GetContext();
4416 CHECK_NULL_RETURN(pipeline, false);
4417 pipeline->SendUpdateVirtualNodeFocusEvent();
4418 return true;
4419 }
4420
SyncGeometryNode(bool needSyncRsNode,const DirtySwapConfig & config)4421 void FrameNode::SyncGeometryNode(bool needSyncRsNode, const DirtySwapConfig& config)
4422 {
4423 if (SystemProperties::GetSyncDebugTraceEnabled()) {
4424 ACE_LAYOUT_TRACE_BEGIN("SyncGeometryNode[%s][self:%d][parent:%d][key:%s]", GetTag().c_str(), GetId(),
4425 GetParent() ? GetParent()->GetId() : 0, GetInspectorIdValue("").c_str());
4426 ACE_LAYOUT_TRACE_END()
4427 }
4428
4429 // update border.
4430 if (layoutProperty_->GetBorderWidthProperty()) {
4431 if (!renderContext_->HasBorderColor()) {
4432 BorderColorProperty borderColorProperty;
4433 borderColorProperty.SetColor(Color::BLACK);
4434 renderContext_->UpdateBorderColor(borderColorProperty);
4435 }
4436 if (!renderContext_->HasBorderStyle()) {
4437 BorderStyleProperty borderStyleProperty;
4438 borderStyleProperty.SetBorderStyle(BorderStyle::SOLID);
4439 renderContext_->UpdateBorderStyle(borderStyleProperty);
4440 }
4441 if (!renderContext_->HasDashGap()) {
4442 BorderWidthProperty dashGapProperty;
4443 dashGapProperty.SetBorderWidth(Dimension(-1));
4444 renderContext_->UpdateDashGap(dashGapProperty);
4445 }
4446 if (!renderContext_->HasDashWidth()) {
4447 BorderWidthProperty dashWidthProperty;
4448 dashWidthProperty.SetBorderWidth(Dimension(-1));
4449 renderContext_->UpdateDashWidth(dashWidthProperty);
4450 }
4451 if (layoutProperty_->GetLayoutConstraint().has_value()) {
4452 renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
4453 ScaleProperty::CreateScaleProperty(),
4454 layoutProperty_->GetLayoutConstraint()->percentReference.Width()));
4455 } else {
4456 renderContext_->UpdateBorderWidthF(ConvertToBorderWidthPropertyF(layoutProperty_->GetBorderWidthProperty(),
4457 ScaleProperty::CreateScaleProperty(), PipelineContext::GetCurrentRootWidth()));
4458 }
4459 }
4460
4461 pattern_->OnSyncGeometryNode(config);
4462 if (needSyncRsNode) {
4463 pattern_->BeforeSyncGeometryProperties(config);
4464 renderContext_->SyncGeometryProperties(RawPtr(geometryNode_), true, layoutProperty_->GetPixelRound());
4465 if (SystemProperties::GetSyncDebugTraceEnabled()) {
4466 ACE_LAYOUT_TRACE_BEGIN("TriggerOnSizeChangeNode:[%s][id:%d]", GetTag().c_str(), GetId());
4467 ACE_LAYOUT_TRACE_END()
4468 }
4469 TriggerOnSizeChangeCallback();
4470 }
4471
4472 // update background
4473 if (builderFunc_) {
4474 auto builderNode = builderFunc_();
4475 auto columnNode = FrameNode::CreateFrameNode(V2::COLUMN_ETS_TAG, ElementRegister::GetInstance()->MakeUniqueId(),
4476 AceType::MakeRefPtr<LinearLayoutPattern>(true));
4477 if (builderNode) {
4478 builderNode->MountToParent(columnNode);
4479 }
4480 SetBackgroundLayoutConstraint(columnNode);
4481 renderContext_->CreateBackgroundPixelMap(columnNode);
4482 builderFunc_ = nullptr;
4483 backgroundNode_ = columnNode;
4484 }
4485
4486 // update focus state
4487 UpdateFocusState();
4488
4489 // rebuild child render node.
4490 if (!isLayoutNode_) {
4491 RebuildRenderContextTree();
4492 } else if (GetParent()) {
4493 GetParent()->RebuildRenderContextTree();
4494 }
4495
4496 /* Adjust components' position which have been set grid properties */
4497 AdjustGridOffset();
4498 }
4499
GetOrCreateChildByIndex(uint32_t index,bool addToRenderTree,bool isCache)4500 RefPtr<LayoutWrapper> FrameNode::GetOrCreateChildByIndex(uint32_t index, bool addToRenderTree, bool isCache)
4501 {
4502 auto child = frameProxy_->GetFrameNodeByIndex(index, true, isCache, addToRenderTree);
4503 if (child) {
4504 child->SetSkipSyncGeometryNode(SkipSyncGeometryNode());
4505 if (addToRenderTree) {
4506 child->SetActive(true);
4507 }
4508 }
4509 return child;
4510 }
4511
GetChildByIndex(uint32_t index,bool isCache)4512 RefPtr<LayoutWrapper> FrameNode::GetChildByIndex(uint32_t index, bool isCache)
4513 {
4514 return frameProxy_->GetFrameNodeByIndex(index, false, isCache, false);
4515 }
4516
GetFrameNodeChildByIndex(uint32_t index,bool isCache,bool isExpand)4517 FrameNode* FrameNode::GetFrameNodeChildByIndex(uint32_t index, bool isCache, bool isExpand)
4518 {
4519 auto frameNode = isExpand ? DynamicCast<FrameNode>(frameProxy_->GetFrameNodeByIndex(index, true, isCache, false))
4520 : DynamicCast<FrameNode>(UINode::GetFrameChildByIndexWithoutExpanded(index));
4521 return RawPtr(frameNode);
4522 }
4523
GetFrameNodeChildByIndexWithoutBuild(uint32_t index)4524 FrameNode* FrameNode::GetFrameNodeChildByIndexWithoutBuild(uint32_t index)
4525 {
4526 auto frameNode = DynamicCast<FrameNode>(UINode::GetFrameChildByIndex(index, false, false, false));
4527 return RawPtr(frameNode);
4528 }
4529
GetChildTrueIndex(const RefPtr<LayoutWrapper> & child) const4530 int32_t FrameNode::GetChildTrueIndex(const RefPtr<LayoutWrapper>& child) const
4531 {
4532 return frameProxy_->GetChildIndex(child);
4533 }
4534
GetChildTrueTotalCount() const4535 uint32_t FrameNode::GetChildTrueTotalCount() const
4536 {
4537 return frameProxy_->GetTotalCount();
4538 }
4539
GetAllChildrenWithBuild(bool addToRenderTree)4540 ChildrenListWithGuard FrameNode::GetAllChildrenWithBuild(bool addToRenderTree)
4541 {
4542 const auto& children = frameProxy_->GetAllFrameChildren();
4543 {
4544 auto guard = frameProxy_->GetGuard();
4545 for (const auto& child : children) {
4546 if (addToRenderTree) {
4547 child->SetActive(true);
4548 }
4549 child->SetSkipSyncGeometryNode(SkipSyncGeometryNode());
4550 }
4551 }
4552 return children;
4553 }
4554
RemoveAllChildInRenderTree()4555 void FrameNode::RemoveAllChildInRenderTree()
4556 {
4557 frameProxy_->RemoveAllChildInRenderTree();
4558 }
4559
SetActiveChildRange(int32_t start,int32_t end,int32_t cacheStart,int32_t cacheEnd,bool showCached)4560 void FrameNode::SetActiveChildRange(int32_t start, int32_t end, int32_t cacheStart, int32_t cacheEnd, bool showCached)
4561 {
4562 frameProxy_->SetActiveChildRange(start, end, cacheStart, cacheEnd, showCached);
4563 }
4564
SetActiveChildRange(const std::optional<ActiveChildSets> & activeChildSets,const std::optional<ActiveChildRange> & activeChildRange)4565 void FrameNode::SetActiveChildRange(
4566 const std::optional<ActiveChildSets>& activeChildSets, const std::optional<ActiveChildRange>& activeChildRange)
4567 {
4568 frameProxy_->SetActiveChildRange(activeChildSets, activeChildRange);
4569 }
4570
RecycleItemsByIndex(int32_t start,int32_t end)4571 void FrameNode::RecycleItemsByIndex(int32_t start, int32_t end)
4572 {
4573 frameProxy_->RecycleItemsByIndex(start, end);
4574 }
4575
RemoveChildInRenderTree(uint32_t index)4576 void FrameNode::RemoveChildInRenderTree(uint32_t index)
4577 {
4578 frameProxy_->RemoveChildInRenderTree(index);
4579 }
4580
SkipMeasureContent() const4581 bool FrameNode::SkipMeasureContent() const
4582 {
4583 return layoutAlgorithm_ && layoutAlgorithm_->SkipMeasure();
4584 }
4585
CheckNeedForceMeasureAndLayout()4586 bool FrameNode::CheckNeedForceMeasureAndLayout()
4587 {
4588 PropertyChangeFlag flag = layoutProperty_->GetPropertyChangeFlag();
4589 return CheckNeedMeasure(flag) || CheckNeedLayout(flag);
4590 }
4591
GetOffsetInScreen()4592 OffsetF FrameNode::GetOffsetInScreen()
4593 {
4594 auto frameOffset = GetPaintRectOffset(false, true);
4595 auto pipelineContext = PipelineContext::GetCurrentContext();
4596 CHECK_NULL_RETURN(pipelineContext, OffsetF(0.0f, 0.0f));
4597 auto window = pipelineContext->GetWindow();
4598 CHECK_NULL_RETURN(window, OffsetF(0.0f, 0.0f));
4599 auto windowOffset = window->GetCurrentWindowRect().GetOffset();
4600 frameOffset += OffsetT<float> { windowOffset.GetX(), windowOffset.GetY() };
4601 return frameOffset;
4602 }
4603
GetOffsetInSubwindow(const OffsetF & subwindowOffset)4604 OffsetF FrameNode::GetOffsetInSubwindow(const OffsetF& subwindowOffset)
4605 {
4606 auto frameOffset = GetOffsetInScreen();
4607 frameOffset -= subwindowOffset;
4608 return frameOffset;
4609 }
4610
GetPixelMap()4611 RefPtr<PixelMap> FrameNode::GetPixelMap()
4612 {
4613 auto gestureHub = GetOrCreateGestureEventHub();
4614 CHECK_NULL_RETURN(gestureHub, nullptr);
4615 RefPtr<PixelMap> pixelMap = gestureHub->GetPixelMap();
4616 // if gesture already have pixel map return directly
4617 if (pixelMap) {
4618 return pixelMap;
4619 }
4620 CHECK_NULL_RETURN(renderContext_, nullptr);
4621 pixelMap = renderContext_->GetThumbnailPixelMap();
4622 gestureHub->SetPixelMap(pixelMap);
4623 return pixelMap;
4624 }
4625
GetBaselineDistance() const4626 float FrameNode::GetBaselineDistance() const
4627 {
4628 const auto& children = frameProxy_->GetAllFrameChildren();
4629 if (children.empty()) {
4630 return geometryNode_->GetBaselineDistance();
4631 }
4632 float distance = 0.0;
4633 {
4634 auto guard = frameProxy_->GetGuard();
4635 for (const auto& child : children) {
4636 float childBaseline = child->GetBaselineDistance();
4637 distance = NearZero(distance) ? childBaseline : std::min(distance, childBaseline);
4638 }
4639 }
4640 return distance;
4641 }
4642
MarkNeedSyncRenderTree(bool needRebuild)4643 void FrameNode::MarkNeedSyncRenderTree(bool needRebuild)
4644 {
4645 if (isLayoutNode_ && GetParent()) {
4646 GetParent()->MarkNeedSyncRenderTree(needRebuild);
4647 }
4648 if (needRebuild) {
4649 frameProxy_->ResetChildren(true);
4650 }
4651 needSyncRenderTree_ = true;
4652 }
4653
GetFrameChildByIndex(uint32_t index,bool needBuild,bool isCache,bool addToRenderTree)4654 RefPtr<UINode> FrameNode::GetFrameChildByIndex(uint32_t index, bool needBuild, bool isCache, bool addToRenderTree)
4655 {
4656 if (index != 0) {
4657 return nullptr;
4658 }
4659 return Claim(this);
4660 }
4661
GetFrameChildByIndexWithoutExpanded(uint32_t index)4662 RefPtr<UINode> FrameNode::GetFrameChildByIndexWithoutExpanded(uint32_t index)
4663 {
4664 return GetFrameChildByIndex(index, false);
4665 }
4666
GetLayoutAlgorithm(bool needReset)4667 const RefPtr<LayoutAlgorithmWrapper>& FrameNode::GetLayoutAlgorithm(bool needReset)
4668 {
4669 if ((!layoutAlgorithm_ || (needReset && layoutAlgorithm_->IsExpire())) && pattern_) {
4670 layoutAlgorithm_ = MakeRefPtr<LayoutAlgorithmWrapper>(pattern_->CreateLayoutAlgorithm());
4671 }
4672 if (needReset) {
4673 layoutAlgorithm_->SetNeedMeasure();
4674 }
4675 return layoutAlgorithm_;
4676 }
4677
SetCacheCount(int32_t cacheCount,const std::optional<LayoutConstraintF> & itemConstraint)4678 void FrameNode::SetCacheCount(int32_t cacheCount, const std::optional<LayoutConstraintF>& itemConstraint)
4679 {
4680 frameProxy_->SetCacheCount(cacheCount, itemConstraint);
4681 }
4682
LayoutOverlay()4683 void FrameNode::LayoutOverlay()
4684 {
4685 auto size = geometryNode_->GetFrameSize();
4686 auto align = Alignment::TOP_LEFT;
4687 Dimension offsetX, offsetY;
4688 auto childLayoutProperty = overlayNode_->GetLayoutProperty();
4689 childLayoutProperty->GetOverlayOffset(offsetX, offsetY);
4690 auto offset = OffsetF(offsetX.ConvertToPx(), offsetY.ConvertToPx());
4691 if (childLayoutProperty->GetPositionProperty()) {
4692 align = childLayoutProperty->GetPositionProperty()->GetAlignment().value_or(align);
4693 }
4694
4695 auto childSize = overlayNode_->GetGeometryNode()->GetMarginFrameSize();
4696 auto translate = Alignment::GetAlignPosition(size, childSize, align) + offset;
4697 overlayNode_->GetGeometryNode()->SetMarginFrameOffset(translate);
4698 overlayNode_->Layout();
4699 }
4700
DoRemoveChildInRenderTree(uint32_t index,bool isAll)4701 void FrameNode::DoRemoveChildInRenderTree(uint32_t index, bool isAll)
4702 {
4703 isActive_ = false;
4704 SetActive(false);
4705 }
4706
DoSetActiveChildRange(int32_t start,int32_t end,int32_t cacheStart,int32_t cacheEnd,bool showCache)4707 void FrameNode::DoSetActiveChildRange(int32_t start, int32_t end, int32_t cacheStart, int32_t cacheEnd, bool showCache)
4708 {
4709 if (showCache) {
4710 start -= cacheStart;
4711 end += cacheEnd;
4712 }
4713 if (start <= end) {
4714 if (start > 0 || end < 0) {
4715 SetActive(false);
4716 SetJSViewActive(false);
4717 } else {
4718 SetActive(true);
4719 SetJSViewActive(true);
4720 }
4721 } else {
4722 if (end < 0 && start > 0) {
4723 SetActive(false);
4724 SetJSViewActive(false);
4725 } else {
4726 SetActive(true);
4727 SetJSViewActive(true);
4728 }
4729 }
4730 }
4731
OnInspectorIdUpdate(const std::string & id)4732 void FrameNode::OnInspectorIdUpdate(const std::string& id)
4733 {
4734 renderContext_->UpdateNodeName(id);
4735 ElementRegister::GetInstance()->AddFrameNodeByInspectorId(id, AceType::WeakClaim(this));
4736 auto parent = GetAncestorNodeOfFrame(true);
4737 if (parent && parent->GetTag() == V2::RELATIVE_CONTAINER_ETS_TAG) {
4738 parent->MarkDirtyNode(PROPERTY_UPDATE_MEASURE_SELF);
4739 }
4740 if (Recorder::EventRecorder::Get().IsExposureRecordEnable()) {
4741 if (exposureProcessor_) {
4742 return;
4743 }
4744 auto* context = GetContext();
4745 CHECK_NULL_VOID(context);
4746 context->AddAfterRenderTask([weak = WeakClaim(this), inspectorId = id]() {
4747 auto host = weak.Upgrade();
4748 CHECK_NULL_VOID(host);
4749 auto pageUrl = Recorder::GetPageUrlByNode(host);
4750 host->exposureProcessor_ = MakeRefPtr<Recorder::ExposureProcessor>(pageUrl, inspectorId);
4751 if (!host->exposureProcessor_->IsNeedRecord()) {
4752 return;
4753 }
4754 host->RecordExposureInner();
4755 });
4756 }
4757 }
4758
SetExposureProcessor(const RefPtr<Recorder::ExposureProcessor> & processor)4759 void FrameNode::SetExposureProcessor(const RefPtr<Recorder::ExposureProcessor>& processor)
4760 {
4761 if (exposureProcessor_ && exposureProcessor_->isListening()) {
4762 return;
4763 } else {
4764 exposureProcessor_ = MakeRefPtr<Recorder::ExposureProcessor>(processor);
4765 exposureProcessor_->SetContainerId(processor->GetContainerId());
4766 }
4767 exposureProcessor_->OnVisibleChange(true, "");
4768 RecordExposureInner();
4769 }
4770
RecordExposureInner()4771 void FrameNode::RecordExposureInner()
4772 {
4773 auto pipeline = GetContext();
4774 if (!pipeline) {
4775 auto piplineRef = PipelineContext::GetContextByContainerId(exposureProcessor_->GetContainerId());
4776 if (!piplineRef) {
4777 pipeline = piplineRef.GetRawPtr();
4778 }
4779 }
4780 CHECK_NULL_VOID(pipeline);
4781 auto callback = [weak = WeakClaim(RawPtr(exposureProcessor_)), weakNode = WeakClaim(this)](
4782 bool visible, double ratio) {
4783 auto processor = weak.Upgrade();
4784 CHECK_NULL_VOID(processor);
4785 if (!visible) {
4786 auto host = weakNode.Upgrade();
4787 auto param = host ? host->GetAutoEventParamValue("") : "";
4788 processor->OnVisibleChange(false, param);
4789 } else {
4790 processor->OnVisibleChange(visible);
4791 }
4792 };
4793 std::vector<double> ratios = { exposureProcessor_->GetRatio() };
4794 pipeline->AddVisibleAreaChangeNode(Claim(this), ratios, callback, false);
4795 exposureProcessor_->SetListenState(true);
4796 }
4797
AddFrameNodeSnapshot(bool isHit,int32_t parentId,std::vector<RectF> responseRegionList,EventTreeType type)4798 void FrameNode::AddFrameNodeSnapshot(
4799 bool isHit, int32_t parentId, std::vector<RectF> responseRegionList, EventTreeType type)
4800 {
4801 auto context = PipelineContext::GetCurrentContext();
4802 CHECK_NULL_VOID(context);
4803 auto eventMgr = context->GetEventManager();
4804 CHECK_NULL_VOID(eventMgr);
4805
4806 FrameNodeSnapshot info = { .nodeId = GetId(),
4807 .parentNodeId = parentId,
4808 .tag = GetTag(),
4809 .comId = propInspectorId_.value_or(""),
4810 .monopolizeEvents = GetMonopolizeEvents(),
4811 .isHit = isHit,
4812 .hitTestMode = static_cast<int32_t>(GetHitTestMode()),
4813 .responseRegionList = responseRegionList };
4814 eventMgr->GetEventTreeRecord(type).AddFrameNodeSnapshot(std::move(info));
4815 }
4816
GetUiExtensionId()4817 int32_t FrameNode::GetUiExtensionId()
4818 {
4819 if (pattern_) {
4820 return pattern_->GetUiExtensionId();
4821 }
4822 return -1;
4823 }
4824
WrapExtensionAbilityId(int64_t extensionOffset,int64_t abilityId)4825 int64_t FrameNode::WrapExtensionAbilityId(int64_t extensionOffset, int64_t abilityId)
4826 {
4827 if (pattern_) {
4828 return pattern_->WrapExtensionAbilityId(extensionOffset, abilityId);
4829 }
4830 return -1;
4831 }
4832
SearchExtensionElementInfoByAccessibilityIdNG(int64_t elementId,int32_t mode,int64_t offset,std::list<Accessibility::AccessibilityElementInfo> & output)4833 void FrameNode::SearchExtensionElementInfoByAccessibilityIdNG(
4834 int64_t elementId, int32_t mode, int64_t offset, std::list<Accessibility::AccessibilityElementInfo>& output)
4835 {
4836 if (pattern_) {
4837 pattern_->SearchExtensionElementInfoByAccessibilityId(elementId, mode, offset, output);
4838 }
4839 }
4840
SearchElementInfosByTextNG(int64_t elementId,const std::string & text,int64_t offset,std::list<Accessibility::AccessibilityElementInfo> & output)4841 void FrameNode::SearchElementInfosByTextNG(int64_t elementId, const std::string& text, int64_t offset,
4842 std::list<Accessibility::AccessibilityElementInfo>& output)
4843 {
4844 if (pattern_) {
4845 pattern_->SearchElementInfosByText(elementId, text, offset, output);
4846 }
4847 }
4848
FindFocusedExtensionElementInfoNG(int64_t elementId,int32_t focusType,int64_t offset,Accessibility::AccessibilityElementInfo & output)4849 void FrameNode::FindFocusedExtensionElementInfoNG(
4850 int64_t elementId, int32_t focusType, int64_t offset, Accessibility::AccessibilityElementInfo& output)
4851 {
4852 if (pattern_) {
4853 pattern_->FindFocusedElementInfo(elementId, focusType, offset, output);
4854 }
4855 }
4856
FocusMoveSearchNG(int64_t elementId,int32_t direction,int64_t offset,Accessibility::AccessibilityElementInfo & output)4857 void FrameNode::FocusMoveSearchNG(
4858 int64_t elementId, int32_t direction, int64_t offset, Accessibility::AccessibilityElementInfo& output)
4859 {
4860 if (pattern_) {
4861 pattern_->FocusMoveSearch(elementId, direction, offset, output);
4862 }
4863 }
4864
TransferExecuteAction(int64_t elementId,const std::map<std::string,std::string> & actionArguments,int32_t action,int64_t offset)4865 bool FrameNode::TransferExecuteAction(
4866 int64_t elementId, const std::map<std::string, std::string>& actionArguments, int32_t action, int64_t offset)
4867 {
4868 bool isExecuted = false;
4869 if (pattern_) {
4870 isExecuted = pattern_->TransferExecuteAction(elementId, actionArguments, action, offset);
4871 }
4872 return isExecuted;
4873 }
4874
GetOnChildTouchTestRet(const std::vector<TouchTestInfo> & touchInfo)4875 TouchResult FrameNode::GetOnChildTouchTestRet(const std::vector<TouchTestInfo>& touchInfo)
4876 {
4877 TouchResult res;
4878 res.strategy = TouchTestStrategy::DEFAULT;
4879
4880 auto func = GetOnTouchTestFunc();
4881 if (func == nullptr) {
4882 return res;
4883 }
4884 return func(touchInfo);
4885 }
4886
GetOnTouchTestFunc()4887 OnChildTouchTestFunc FrameNode::GetOnTouchTestFunc()
4888 {
4889 auto gestureHub = eventHub_->GetGestureEventHub();
4890 if (gestureHub == nullptr) {
4891 return nullptr;
4892 }
4893 auto& func = gestureHub->GetOnTouchTestFunc();
4894 return func;
4895 }
4896
CollectTouchInfos(const PointF & globalPoint,const PointF & parentRevertPoint,std::vector<TouchTestInfo> & touchInfos)4897 void FrameNode::CollectTouchInfos(
4898 const PointF& globalPoint, const PointF& parentRevertPoint, std::vector<TouchTestInfo>& touchInfos)
4899 {
4900 if (GetOnTouchTestFunc() == nullptr) {
4901 return;
4902 }
4903
4904 for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
4905 const auto& child = iter->Upgrade();
4906 if (!child) {
4907 continue;
4908 }
4909
4910 TouchTestInfo info;
4911 if (!child->GetInspectorId().has_value()) {
4912 continue;
4913 }
4914 info.id = child->GetInspectorId().value();
4915 info.windowPoint = globalPoint;
4916 info.currentCmpPoint = parentRevertPoint;
4917
4918 auto renderContext = child->GetRenderContext();
4919 CHECK_NULL_VOID(renderContext);
4920 auto origRect = renderContext->GetPaintRectWithoutTransform();
4921 auto revertPoint = parentRevertPoint;
4922 renderContext->GetPointWithRevert(revertPoint);
4923 auto subRevertPoint = revertPoint - origRect.GetOffset();
4924 info.subCmpPoint = subRevertPoint;
4925
4926 info.subRect = child->GetGeometryNode()->GetFrameRect();
4927
4928 touchInfos.emplace_back(info);
4929 }
4930 }
4931
GetDispatchFrameNode(const TouchResult & touchRes)4932 RefPtr<FrameNode> FrameNode::GetDispatchFrameNode(const TouchResult& touchRes)
4933 {
4934 if (touchRes.strategy != TouchTestStrategy::FORWARD_COMPETITION &&
4935 touchRes.strategy != TouchTestStrategy::FORWARD) {
4936 return nullptr;
4937 }
4938
4939 for (auto iter = frameChildren_.rbegin(); iter != frameChildren_.rend(); ++iter) {
4940 const auto& child = iter->Upgrade();
4941 if (!child) {
4942 continue;
4943 }
4944 std::string id = child->GetInspectorId().value_or("");
4945 if ((!touchRes.id.empty()) && (touchRes.id == id)) {
4946 return child;
4947 }
4948 }
4949 return nullptr;
4950 }
4951
CalculateCachedTransformRelativeOffset(uint64_t nanoTimestamp)4952 OffsetF FrameNode::CalculateCachedTransformRelativeOffset(uint64_t nanoTimestamp)
4953 {
4954 auto context = GetRenderContext();
4955 CHECK_NULL_RETURN(context, OffsetF());
4956 auto offset = context->GetPaintRectWithTransform().GetOffset();
4957
4958 auto parent = GetAncestorNodeOfFrame(true);
4959 if (parent) {
4960 auto parentTimestampOffset = parent->GetCachedTransformRelativeOffset();
4961 if (parentTimestampOffset.first == nanoTimestamp) {
4962 auto result = offset + parentTimestampOffset.second;
4963 SetCachedTransformRelativeOffset({ nanoTimestamp, result });
4964 return result;
4965 }
4966 auto result = offset + parent->CalculateCachedTransformRelativeOffset(nanoTimestamp);
4967 SetCachedTransformRelativeOffset({ nanoTimestamp, result });
4968 return result;
4969 }
4970 SetCachedTransformRelativeOffset({ nanoTimestamp, offset });
4971 return offset;
4972 }
4973
CalculateOffsetRelativeToWindow(uint64_t nanoTimestamp)4974 OffsetF FrameNode::CalculateOffsetRelativeToWindow(uint64_t nanoTimestamp)
4975 {
4976 auto currOffset = geometryNode_->GetFrameOffset();
4977 if (renderContext_ && renderContext_->GetPositionProperty()) {
4978 if (renderContext_->GetPositionProperty()->HasPosition()) {
4979 auto renderPosition =
4980 ContextPositionConvertToPX(renderContext_, layoutProperty_->GetLayoutConstraint()->percentReference);
4981 currOffset.SetX(static_cast<float>(renderPosition.first));
4982 currOffset.SetY(static_cast<float>(renderPosition.second));
4983 }
4984 }
4985
4986 auto parent = GetAncestorNodeOfFrame(true);
4987 if (parent) {
4988 auto parentTimestampOffset = parent->GetCachedGlobalOffset();
4989 if (parentTimestampOffset.first == nanoTimestamp) {
4990 auto result = currOffset + parentTimestampOffset.second;
4991 SetCachedGlobalOffset({ nanoTimestamp, result });
4992 return result;
4993 } else {
4994 auto result = currOffset + parent->CalculateOffsetRelativeToWindow(nanoTimestamp);
4995 SetCachedGlobalOffset({ nanoTimestamp, result });
4996 return result;
4997 }
4998 } else {
4999 SetCachedGlobalOffset({ nanoTimestamp, currOffset });
5000 return currOffset;
5001 }
5002 }
5003
GetNodeContainer()5004 RefPtr<FrameNode> FrameNode::GetNodeContainer()
5005 {
5006 if (GetTag() == V2::NODE_CONTAINER_ETS_TAG) {
5007 return Claim(this);
5008 }
5009 auto parent = GetParent();
5010 while (parent && parent->GetTag() != V2::NODE_CONTAINER_ETS_TAG) {
5011 parent = parent->GetParent();
5012 }
5013 return AceType::DynamicCast<FrameNode>(parent);
5014 }
5015
InitLastArea()5016 void FrameNode::InitLastArea()
5017 {
5018 if (!lastFrameRect_) {
5019 lastFrameRect_ = std::make_unique<RectF>();
5020 }
5021 if (!lastParentOffsetToWindow_) {
5022 lastParentOffsetToWindow_ = std::make_unique<OffsetF>();
5023 }
5024 }
5025
SetParentLayoutConstraint(const SizeF & size) const5026 bool FrameNode::SetParentLayoutConstraint(const SizeF& size) const
5027 {
5028 LayoutConstraintF layoutConstraint;
5029 layoutConstraint.UpdatePercentReference(size);
5030 layoutConstraint.UpdateMaxSizeWithCheck(size);
5031 layoutConstraint.UpdateIllegalParentIdealSizeWithCheck(OptionalSize(size));
5032 layoutProperty_->UpdateParentLayoutConstraint(layoutConstraint);
5033 return true;
5034 }
5035
ForceSyncGeometryNode()5036 void FrameNode::ForceSyncGeometryNode()
5037 {
5038 CHECK_NULL_VOID(renderContext_);
5039 oldGeometryNode_.Reset();
5040 renderContext_->SavePaintRect();
5041 renderContext_->SyncGeometryProperties(RawPtr(geometryNode_));
5042 }
5043
GetCachedGlobalOffset() const5044 const std::pair<uint64_t, OffsetF>& FrameNode::GetCachedGlobalOffset() const
5045 {
5046 return cachedGlobalOffset_;
5047 }
5048
SetCachedGlobalOffset(const std::pair<uint64_t,OffsetF> & timestampOffset)5049 void FrameNode::SetCachedGlobalOffset(const std::pair<uint64_t, OffsetF>& timestampOffset)
5050 {
5051 cachedGlobalOffset_ = timestampOffset;
5052 }
GetCachedTransformRelativeOffset() const5053 const std::pair<uint64_t, OffsetF>& FrameNode::GetCachedTransformRelativeOffset() const
5054 {
5055 return cachedTransformRelativeOffset_;
5056 }
5057
SetCachedTransformRelativeOffset(const std::pair<uint64_t,OffsetF> & timestampOffset)5058 void FrameNode::SetCachedTransformRelativeOffset(const std::pair<uint64_t, OffsetF>& timestampOffset)
5059 {
5060 cachedTransformRelativeOffset_ = timestampOffset;
5061 }
5062
PaintDebugBoundary(bool flag)5063 void FrameNode::PaintDebugBoundary(bool flag)
5064 {
5065 if (!isActive_) {
5066 return;
5067 }
5068 if (renderContext_) {
5069 renderContext_->PaintDebugBoundary(flag);
5070 }
5071 }
5072
TriggerOnTouchIntercept(const TouchEvent & touchEvent)5073 HitTestMode FrameNode::TriggerOnTouchIntercept(const TouchEvent& touchEvent)
5074 {
5075 auto gestureHub = eventHub_->GetGestureEventHub();
5076 CHECK_NULL_RETURN(gestureHub, HitTestMode::HTMDEFAULT);
5077 auto onTouchIntercept = gestureHub->GetOnTouchIntercept();
5078 CHECK_NULL_RETURN(onTouchIntercept, HitTestMode::HTMDEFAULT);
5079 TouchEventInfo event("touchEvent");
5080 event.SetTimeStamp(touchEvent.time);
5081 event.SetDeviceId(touchEvent.deviceId);
5082 event.SetPointerEvent(touchEvent.pointerEvent);
5083 TouchLocationInfo changedInfo("onTouch", touchEvent.originalId);
5084 PointF lastLocalPoint(touchEvent.x, touchEvent.y);
5085 NGGestureRecognizer::Transform(lastLocalPoint, Claim(this), false, false);
5086 auto localX = static_cast<float>(lastLocalPoint.GetX());
5087 auto localY = static_cast<float>(lastLocalPoint.GetY());
5088 changedInfo.SetLocalLocation(Offset(localX, localY));
5089 changedInfo.SetGlobalLocation(Offset(touchEvent.x, touchEvent.y));
5090 changedInfo.SetScreenLocation(Offset(touchEvent.screenX, touchEvent.screenY));
5091 changedInfo.SetTouchType(touchEvent.type);
5092 changedInfo.SetForce(touchEvent.force);
5093 changedInfo.SetPressedTime(touchEvent.pressedTime);
5094 changedInfo.SetWidth(touchEvent.width);
5095 changedInfo.SetHeight(touchEvent.height);
5096 if (touchEvent.tiltX.has_value()) {
5097 changedInfo.SetTiltX(touchEvent.tiltX.value());
5098 }
5099 if (touchEvent.tiltY.has_value()) {
5100 changedInfo.SetTiltY(touchEvent.tiltY.value());
5101 }
5102 changedInfo.SetSourceTool(touchEvent.sourceTool);
5103 event.AddChangedTouchLocationInfo(std::move(changedInfo));
5104
5105 AddTouchEventAllFingersInfo(event, touchEvent);
5106 event.SetSourceDevice(touchEvent.sourceType);
5107 event.SetForce(touchEvent.force);
5108 if (touchEvent.tiltX.has_value()) {
5109 event.SetTiltX(touchEvent.tiltX.value());
5110 }
5111 if (touchEvent.tiltY.has_value()) {
5112 event.SetTiltY(touchEvent.tiltY.value());
5113 }
5114 event.SetSourceTool(touchEvent.sourceTool);
5115 EventTarget eventTarget;
5116 eventTarget.id = GetInspectorId().value_or("").c_str();
5117 event.SetTarget(eventTarget);
5118 auto result = onTouchIntercept(event);
5119 SetHitTestMode(result);
5120 return result;
5121 }
5122
AddTouchEventAllFingersInfo(TouchEventInfo & event,const TouchEvent & touchEvent)5123 void FrameNode::AddTouchEventAllFingersInfo(TouchEventInfo& event, const TouchEvent& touchEvent)
5124 {
5125 // all fingers collection
5126 for (const auto& item : touchEvent.pointers) {
5127 float globalX = item.x;
5128 float globalY = item.y;
5129 float screenX = item.screenX;
5130 float screenY = item.screenY;
5131 PointF localPoint(globalX, globalY);
5132 NGGestureRecognizer::Transform(localPoint, Claim(this), false, false);
5133 auto localX = static_cast<float>(localPoint.GetX());
5134 auto localY = static_cast<float>(localPoint.GetY());
5135 TouchLocationInfo info("onTouch", item.originalId);
5136 info.SetGlobalLocation(Offset(globalX, globalY));
5137 info.SetLocalLocation(Offset(localX, localY));
5138 info.SetScreenLocation(Offset(screenX, screenY));
5139 info.SetTouchType(touchEvent.type);
5140 info.SetForce(item.force);
5141 info.SetPressedTime(item.downTime);
5142 info.SetWidth(item.width);
5143 info.SetHeight(item.height);
5144 if (item.tiltX.has_value()) {
5145 info.SetTiltX(item.tiltX.value());
5146 }
5147 if (item.tiltY.has_value()) {
5148 info.SetTiltY(item.tiltY.value());
5149 }
5150 info.SetSourceTool(item.sourceTool);
5151 event.AddTouchLocationInfo(std::move(info));
5152 }
5153 }
5154
AttachContext(PipelineContext * context,bool recursive)5155 void FrameNode::AttachContext(PipelineContext* context, bool recursive)
5156 {
5157 UINode::AttachContext(context, recursive);
5158 eventHub_->OnAttachContext(context);
5159 pattern_->OnAttachContext(context);
5160 }
5161
DetachContext(bool recursive)5162 void FrameNode::DetachContext(bool recursive)
5163 {
5164 CHECK_NULL_VOID(context_);
5165 pattern_->OnDetachContext(context_);
5166 eventHub_->OnDetachContext(context_);
5167 UINode::DetachContext(recursive);
5168 }
5169
ApplyFrameNodeTranformToRect(const RectF & rect,const RefPtr<FrameNode> & parent) const5170 RectF FrameNode::ApplyFrameNodeTranformToRect(const RectF& rect, const RefPtr<FrameNode>& parent) const
5171 {
5172 RectF newRect = rect;
5173 if (!parent) {
5174 return newRect;
5175 }
5176
5177 auto parentRenderContext = parent->GetRenderContext();
5178 if (!parentRenderContext) {
5179 return newRect;
5180 }
5181
5182 auto parentScale = parentRenderContext->GetTransformScale();
5183 auto offset = rect.GetOffset();
5184 if (parentScale) {
5185 newRect.SetWidth(rect.Width() * parentScale.value().x);
5186 newRect.SetHeight(rect.Height() * parentScale.value().y);
5187 offset = OffsetF(offset.GetX() * parentScale.value().x, offset.GetY() * parentScale.value().y);
5188 }
5189 offset += parentRenderContext->GetPaintRectWithTransform().GetOffset();
5190 newRect.SetOffset(offset);
5191 return newRect;
5192 }
5193
GetVisibleRect(RectF & visibleRect,RectF & frameRect) const5194 void FrameNode::GetVisibleRect(RectF& visibleRect, RectF& frameRect) const
5195 {
5196 visibleRect = GetPaintRectWithTransform();
5197 frameRect = visibleRect;
5198 RefPtr<FrameNode> parentUi = GetAncestorNodeOfFrame(true);
5199 if (!parentUi) {
5200 visibleRect.SetWidth(0.0f);
5201 visibleRect.SetHeight(0.0f);
5202 return;
5203 }
5204 while (parentUi) {
5205 visibleRect = ApplyFrameNodeTranformToRect(visibleRect, parentUi);
5206 auto parentRect = parentUi->GetPaintRectWithTransform();
5207 visibleRect = visibleRect.Constrain(parentRect);
5208 if (visibleRect.IsEmpty()) {
5209 return;
5210 }
5211 frameRect = ApplyFrameNodeTranformToRect(frameRect, parentUi);
5212 parentUi = parentUi->GetAncestorNodeOfFrame(true);
5213 }
5214 }
5215
AllowVisibleAreaCheck() const5216 bool FrameNode::AllowVisibleAreaCheck() const
5217 {
5218 return IsOnMainTree() || (pattern_ && pattern_->AllowVisibleAreaCheck());
5219 }
5220
GetVisibleRectWithClip(RectF & visibleRect,RectF & visibleInnerRect,RectF & frameRect,bool withClip) const5221 void FrameNode::GetVisibleRectWithClip(RectF& visibleRect, RectF& visibleInnerRect, RectF& frameRect,
5222 bool withClip) const
5223 {
5224 visibleRect = GetPaintRectWithTransform();
5225 frameRect = visibleRect;
5226 visibleInnerRect = visibleRect;
5227 RefPtr<FrameNode> parentUi = GetAncestorNodeOfFrame(true);
5228 if (!AllowVisibleAreaCheck() || !parentUi || IsFrameDisappear()) {
5229 visibleRect.SetWidth(0.0f);
5230 visibleRect.SetHeight(0.0f);
5231 visibleInnerRect.SetWidth(0.0f);
5232 visibleInnerRect.SetHeight(0.0f);
5233 return;
5234 }
5235
5236 while (parentUi) {
5237 visibleRect = ApplyFrameNodeTranformToRect(visibleRect, parentUi);
5238 auto parentRect = parentUi->GetPaintRectWithTransform();
5239 if (!visibleRect.IsEmpty()) {
5240 visibleRect = visibleRect.Constrain(parentRect);
5241 }
5242
5243 if (isCalculateInnerVisibleRectClip_ || withClip) {
5244 visibleInnerRect = ApplyFrameNodeTranformToRect(visibleInnerRect, parentUi);
5245 auto parentContext = parentUi->GetRenderContext();
5246 if (!visibleInnerRect.IsEmpty() && ((parentContext && parentContext->GetClipEdge().value_or(false)) ||
5247 parentUi->IsWindowBoundary() || parentUi->GetTag() == V2::ROOT_ETS_TAG)) {
5248 visibleInnerRect = visibleInnerRect.Constrain(parentRect);
5249 }
5250 }
5251
5252 if (visibleRect.IsEmpty() && (!(isCalculateInnerVisibleRectClip_ || withClip) || visibleInnerRect.IsEmpty())) {
5253 visibleInnerRect = visibleRect;
5254 return;
5255 }
5256 frameRect = ApplyFrameNodeTranformToRect(frameRect, parentUi);
5257 parentUi = parentUi->GetAncestorNodeOfFrame(true);
5258 }
5259
5260 if (!(isCalculateInnerVisibleRectClip_ || withClip)) {
5261 visibleInnerRect = visibleRect;
5262 }
5263 }
5264
GetCacheVisibleRect(uint64_t timestamp)5265 CacheVisibleRectResult FrameNode::GetCacheVisibleRect(uint64_t timestamp)
5266 {
5267 RefPtr<FrameNode> parentUi = GetAncestorNodeOfFrame(true);
5268 auto rectToParent = GetPaintRectWithTransform();
5269 auto scale = GetTransformScale();
5270
5271 if (!parentUi || IsWindowBoundary()) {
5272 cachedVisibleRectResult_ = {timestamp,
5273 {rectToParent.GetOffset(), rectToParent, rectToParent, scale, rectToParent, rectToParent}};
5274 return cachedVisibleRectResult_.second;
5275 }
5276
5277 if (parentUi->cachedVisibleRectResult_.first == timestamp) {
5278 auto parentCacheVisibleRectResult = parentUi->cachedVisibleRectResult_.second;
5279 return CalculateCacheVisibleRect(parentCacheVisibleRectResult, parentUi, rectToParent, scale, timestamp);
5280 }
5281
5282 CacheVisibleRectResult parentCacheVisibleRectResult = parentUi->GetCacheVisibleRect(timestamp);
5283 return CalculateCacheVisibleRect(parentCacheVisibleRectResult, parentUi, rectToParent, scale, timestamp);
5284 }
5285
CalculateCacheVisibleRect(CacheVisibleRectResult & parentCacheVisibleRect,const RefPtr<FrameNode> & parentUi,RectF & rectToParent,VectorF scale,uint64_t timestamp)5286 CacheVisibleRectResult FrameNode::CalculateCacheVisibleRect(CacheVisibleRectResult& parentCacheVisibleRect,
5287 const RefPtr<FrameNode>& parentUi, RectF& rectToParent, VectorF scale, uint64_t timestamp)
5288 {
5289 auto parentRenderContext = parentUi->GetRenderContext();
5290 OffsetF windowOffset;
5291 auto offset = rectToParent.GetOffset();
5292 if (parentRenderContext && parentRenderContext->GetTransformScale()) {
5293 auto parentScale = parentRenderContext->GetTransformScale();
5294 offset = OffsetF(offset.GetX() * parentScale.value().x, offset.GetY() * parentScale.value().y);
5295 }
5296 windowOffset = parentCacheVisibleRect.windowOffset + offset;
5297
5298 RectF rect;
5299 rect.SetOffset(windowOffset);
5300 rect.SetWidth(rectToParent.Width() * parentCacheVisibleRect.cumulativeScale.x);
5301 rect.SetHeight(rectToParent.Height() * parentCacheVisibleRect.cumulativeScale.y);
5302
5303 auto visibleRect = rect.Constrain(parentCacheVisibleRect.visibleRect);
5304 auto innerVisibleRect = rect;
5305 auto innerBoundaryRect = parentCacheVisibleRect.innerBoundaryRect;
5306 if (parentRenderContext && parentRenderContext->GetClipEdge().value_or(false)) {
5307 innerBoundaryRect = parentCacheVisibleRect.innerVisibleRect.Constrain(innerBoundaryRect);
5308 }
5309 innerVisibleRect = rect.Constrain(innerBoundaryRect);
5310
5311 scale = {scale.x * parentCacheVisibleRect.cumulativeScale.x, scale.y * parentCacheVisibleRect.cumulativeScale.y};
5312 cachedVisibleRectResult_ = { timestamp,
5313 { windowOffset, visibleRect, innerVisibleRect, scale, rect, innerBoundaryRect } };
5314 return {windowOffset, visibleRect, innerVisibleRect, scale, rect, innerBoundaryRect};
5315 }
5316
ChangeSensitiveStyle(bool isSensitive)5317 void FrameNode::ChangeSensitiveStyle(bool isSensitive)
5318 {
5319 pattern_->OnSensitiveStyleChange(isSensitive);
5320 }
5321
IsContextTransparent()5322 bool FrameNode::IsContextTransparent()
5323 {
5324 ACE_SCOPED_TRACE("Transparent detection");
5325 const auto& rect = renderContext_->GetPaintRectWithTransform();
5326 auto width = rect.Width();
5327 auto height = rect.Height();
5328 if (renderContext_->GetOpacity().has_value() && renderContext_->GetOpacity().value() <= MIN_OPACITY) {
5329 return true;
5330 }
5331 if (layoutTags_.find(GetTag()) == layoutTags_.end()) {
5332 if (width > MIN_WIDTH && height > MIN_HEIGHT &&
5333 static_cast<int32_t>(layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)) == 0) {
5334 return false;
5335 }
5336 } else {
5337 if (width > MIN_WIDTH && height > MIN_HEIGHT &&
5338 static_cast<int32_t>(layoutProperty_->GetVisibility().value_or(VisibleType::VISIBLE)) == 0 &&
5339 renderContext_->GetBackgroundColor()->ColorToString().compare("#00000000") != 0) {
5340 return false;
5341 }
5342 }
5343 for (const auto& item : GetChildren()) {
5344 if (!item->IsContextTransparent()) {
5345 return false;
5346 }
5347 }
5348 return true;
5349 }
5350
GetOrRefreshRevertMatrixFromCache(bool forceRefresh)5351 Matrix4& FrameNode::GetOrRefreshRevertMatrixFromCache(bool forceRefresh)
5352 {
5353 auto pipeline = NG::PipelineContext::GetCurrentContext();
5354 CHECK_NULL_RETURN(pipeline, localRevertMatrix_);
5355 auto nanoTimestamp = pipeline->GetVsyncTime();
5356 auto rect = renderContext_->GetPaintRectWithoutTransform();
5357 // the caller is trying to refresh cache forcedly or the cache is invalid
5358 if (!isLocalRevertMatrixAvailable_ || forceRefresh || prePaintRect_ != rect ||
5359 getCacheNanoTime_ + MATRIX_CACHE_TIME_THRESHOLD < nanoTimestamp) {
5360 localRevertMatrix_ = renderContext_->GetRevertMatrix();
5361 isLocalRevertMatrixAvailable_ = true;
5362 getCacheNanoTime_ = nanoTimestamp;
5363 prePaintRect_ = rect;
5364 return localRevertMatrix_;
5365 }
5366
5367 // cache valid
5368 return localRevertMatrix_;
5369 }
5370
5371 // apply the matrix to the given point specified by dst
MapPointTo(PointF & dst,Matrix4 & matrix)5372 void FrameNode::MapPointTo(PointF& dst, Matrix4& matrix)
5373 {
5374 Point tmp(dst.GetX(), dst.GetY());
5375 auto transformPoint = matrix * tmp;
5376 dst.SetX(transformPoint.GetX());
5377 dst.SetY(transformPoint.GetY());
5378 }
5379
SetSuggestOpIncMarked(bool flag)5380 void FrameNode::SetSuggestOpIncMarked(bool flag)
5381 {
5382 if (flag) {
5383 suggestOpIncByte_ |= SUGGEST_OPINC_MARKED_MASK;
5384 } else {
5385 suggestOpIncByte_ &= (~SUGGEST_OPINC_MARKED_MASK);
5386 }
5387 }
5388
GetSuggestOpIncMarked()5389 bool FrameNode::GetSuggestOpIncMarked()
5390 {
5391 return (suggestOpIncByte_ & SUGGEST_OPINC_MARKED_MASK) > 0;
5392 }
5393
SetCanSuggestOpInc(bool flag)5394 void FrameNode::SetCanSuggestOpInc(bool flag)
5395 {
5396 if (flag) {
5397 suggestOpIncByte_ |= CAN_SUGGEST_OPINC_MASK;
5398 } else {
5399 suggestOpIncByte_ &= (~CAN_SUGGEST_OPINC_MASK);
5400 }
5401 }
5402
GetCanSuggestOpInc()5403 bool FrameNode::GetCanSuggestOpInc()
5404 {
5405 return (suggestOpIncByte_ & CAN_SUGGEST_OPINC_MASK) > 0;
5406 }
5407
SetApplicationRenderGroupMarked(bool flag)5408 void FrameNode::SetApplicationRenderGroupMarked(bool flag)
5409 {
5410 if (flag) {
5411 suggestOpIncByte_ |= APP_RENDER_GROUP_MARKED_MASK;
5412 } else {
5413 suggestOpIncByte_ &= (~APP_RENDER_GROUP_MARKED_MASK);
5414 }
5415 }
5416
GetApplicationRenderGroupMarked()5417 bool FrameNode::GetApplicationRenderGroupMarked()
5418 {
5419 return (suggestOpIncByte_ & APP_RENDER_GROUP_MARKED_MASK) > 0;
5420 }
5421
SetSuggestOpIncActivatedOnce()5422 void FrameNode::SetSuggestOpIncActivatedOnce()
5423 {
5424 suggestOpIncByte_ |= SUGGEST_OPINC_ACTIVATED_ONCE;
5425 }
5426
GetSuggestOpIncActivatedOnce()5427 bool FrameNode::GetSuggestOpIncActivatedOnce()
5428 {
5429 return (suggestOpIncByte_ & SUGGEST_OPINC_ACTIVATED_ONCE) > 0;
5430 }
5431
SetOpIncGroupCheckedThrough(bool flag)5432 void FrameNode::SetOpIncGroupCheckedThrough(bool flag)
5433 {
5434 if (flag) {
5435 suggestOpIncByte_ |= SUGGEST_OPINC_CHECKED_THROUGH;
5436 } else {
5437 suggestOpIncByte_ &= (~SUGGEST_OPINC_CHECKED_THROUGH);
5438 }
5439 }
5440
GetOpIncGroupCheckedThrough()5441 bool FrameNode::GetOpIncGroupCheckedThrough()
5442 {
5443 return (suggestOpIncByte_ & SUGGEST_OPINC_CHECKED_THROUGH) > 0;
5444 }
5445
SetOpIncCheckedOnce()5446 void FrameNode::SetOpIncCheckedOnce()
5447 {
5448 suggestOpIncByte_ |= SUGGEST_OPINC_CHCKED_ONCE;
5449 }
GetOpIncCheckedOnce()5450 bool FrameNode::GetOpIncCheckedOnce()
5451 {
5452 return (suggestOpIncByte_ & SUGGEST_OPINC_CHCKED_ONCE) > 0;
5453 }
5454
MarkSuggestOpIncGroup(bool suggest,bool calc)5455 bool FrameNode::MarkSuggestOpIncGroup(bool suggest, bool calc)
5456 {
5457 CHECK_NULL_RETURN(renderContext_, false);
5458 if (!GetSuggestOpIncMarked() && GetCanSuggestOpInc()) {
5459 renderContext_->SuggestOpIncNode(suggest, calc);
5460 SetSuggestOpIncMarked(true);
5461 }
5462 return true;
5463 }
5464
IsOpIncValidNode(const SizeF & boundary,int32_t childNumber)5465 OPINC_TYPE_E FrameNode::IsOpIncValidNode(const SizeF& boundary, int32_t childNumber)
5466 {
5467 auto ret = GetPattern()->OpIncType();
5468 switch (ret) {
5469 case OPINC_NODE:
5470 SetCanSuggestOpInc(true);
5471 break;
5472 case OPINC_PARENT_POSSIBLE:
5473 break;
5474 case OPINC_NODE_POSSIBLE: {
5475 int32_t height = static_cast<int>(GetGeometryNode()->GetFrameSize().Height());
5476 int32_t width = static_cast<int>(GetGeometryNode()->GetFrameSize().Width());
5477 int32_t heightBoundary = static_cast<int>(boundary.Height() * HIGHT_RATIO_LIMIT);
5478 int32_t area = height * width;
5479 if (area >= MIN_OPINC_AREA && height <= heightBoundary) {
5480 SetCanSuggestOpInc(true);
5481 ret = OPINC_NODE;
5482 } else if (height > heightBoundary) {
5483 ret = OPINC_PARENT_POSSIBLE;
5484 } else {
5485 ret = OPINC_SUGGESTED_OR_EXCLUDED;
5486 }
5487 break;
5488 }
5489 default:
5490 break;
5491 }
5492 return ret;
5493 }
5494
GetAllChildren()5495 ChildrenListWithGuard FrameNode::GetAllChildren()
5496 {
5497 // frameProxy_ never be null in frame node;
5498 return frameProxy_->GetCurrentFrameChildren();
5499 }
5500
FindSuggestOpIncNode(std::string & path,const SizeF & boundary,int32_t depth)5501 OPINC_TYPE_E FrameNode::FindSuggestOpIncNode(std::string& path, const SizeF& boundary, int32_t depth)
5502 {
5503 if (GetSuggestOpIncActivatedOnce()) {
5504 return OPINC_SUGGESTED_OR_EXCLUDED;
5505 }
5506 SetSuggestOpIncActivatedOnce();
5507
5508 if (GetApplicationRenderGroupMarked()) {
5509 return OPINC_INVALID;
5510 }
5511 auto status = IsOpIncValidNode(boundary);
5512 if (SystemProperties::GetDebugEnabled()) {
5513 const auto& hostTag = GetHostTag();
5514 path = path + " --> " + hostTag;
5515 LOGD("FindSuggestOpIncNode : %{public}s, with depth %{public}d, boundary: %{public}f, self: %{public}f, "
5516 "status: %{public}d",
5517 path.c_str(), depth, boundary.Height(), GetGeometryNode()->GetFrameSize().Height(), status);
5518 }
5519 if (status == OPINC_NODE) {
5520 MarkSuggestOpIncGroup(true, true);
5521 return OPINC_SUGGESTED_OR_EXCLUDED;
5522 } else if (status == OPINC_SUGGESTED_OR_EXCLUDED) {
5523 return OPINC_SUGGESTED_OR_EXCLUDED;
5524 } else if (status == OPINC_PARENT_POSSIBLE) {
5525 for (auto child : GetAllChildren()) {
5526 if (!child) {
5527 continue;
5528 }
5529 auto frameNode = AceType::DynamicCast<FrameNode>(child);
5530 if (frameNode) {
5531 frameNode->FindSuggestOpIncNode(path, boundary, depth + 1);
5532 }
5533 }
5534 return OPINC_PARENT_POSSIBLE;
5535 } else if (status == OPINC_INVALID) {
5536 return OPINC_INVALID;
5537 }
5538 return OPINC_SUGGESTED_OR_EXCLUDED;
5539 }
5540
MarkAndCheckNewOpIncNode()5541 void FrameNode::MarkAndCheckNewOpIncNode()
5542 {
5543 auto parent = GetAncestorNodeOfFrame(true);
5544 CHECK_NULL_VOID(parent);
5545 if (parent->GetSuggestOpIncActivatedOnce() && !GetSuggestOpIncActivatedOnce()) {
5546 SetSuggestOpIncActivatedOnce();
5547 if (!parent->GetOpIncCheckedOnce()) {
5548 parent->SetOpIncCheckedOnce();
5549 auto status = IsOpIncValidNode(parent->GetGeometryNode()->GetFrameSize());
5550 if (status == OPINC_NODE) {
5551 parent->SetOpIncGroupCheckedThrough(true);
5552 } else if (FrameNode::GetValidLeafChildNumber(Claim(this), THRESH_CHILD_NO) >= THRESH_CHILD_NO) {
5553 parent->SetOpIncGroupCheckedThrough(true);
5554 } else {
5555 parent->SetOpIncGroupCheckedThrough(false);
5556 }
5557 }
5558 if (parent->GetOpIncGroupCheckedThrough()) {
5559 SetCanSuggestOpInc(true);
5560 MarkSuggestOpIncGroup(true, true);
5561 }
5562 }
5563 }
5564
GetValidLeafChildNumber(const RefPtr<FrameNode> & host,int32_t thresh)5565 int FrameNode::GetValidLeafChildNumber(const RefPtr<FrameNode>& host, int32_t thresh)
5566 {
5567 CHECK_NULL_RETURN(host, 0);
5568 auto total = 0;
5569 auto childSize = host->GetTotalChildCount();
5570 if (childSize < 1) {
5571 return 1;
5572 }
5573 for (auto i = 0; i < childSize; i++) {
5574 auto child = AceType::DynamicCast<FrameNode>(host->GetChildByIndex(i));
5575 if (!child) {
5576 continue;
5577 }
5578 total += GetValidLeafChildNumber(child, thresh);
5579 if (total >= thresh) {
5580 return total;
5581 }
5582 }
5583 return total;
5584 }
5585
TriggerShouldParallelInnerWith(const ResponseLinkResult & currentRecognizers,const ResponseLinkResult & responseLinkRecognizers)5586 void FrameNode::TriggerShouldParallelInnerWith(
5587 const ResponseLinkResult& currentRecognizers, const ResponseLinkResult& responseLinkRecognizers)
5588 {
5589 auto gestureHub = eventHub_->GetGestureEventHub();
5590 CHECK_NULL_VOID(gestureHub);
5591 auto shouldBuiltInRecognizerParallelWithFunc = gestureHub->GetParallelInnerGestureToFunc();
5592 CHECK_NULL_VOID(shouldBuiltInRecognizerParallelWithFunc);
5593 std::map<GestureTypeName, std::vector<RefPtr<NGGestureRecognizer>>> sortedResponseLinkRecognizers;
5594
5595 for (const auto& item : responseLinkRecognizers) {
5596 auto recognizer = AceType::DynamicCast<NGGestureRecognizer>(item);
5597 if (!recognizer) {
5598 continue;
5599 }
5600 auto type = recognizer->GetRecognizerType();
5601 sortedResponseLinkRecognizers[type].emplace_back(item);
5602 }
5603
5604 for (const auto& item : currentRecognizers) {
5605 if (!item->IsSystemGesture() || item->GetRecognizerType() != GestureTypeName::PAN_GESTURE) {
5606 continue;
5607 }
5608 auto multiRecognizer = AceType::DynamicCast<MultiFingersRecognizer>(item);
5609 if (!multiRecognizer || multiRecognizer->GetTouchPointsSize() > 1) {
5610 continue;
5611 }
5612 auto iter = sortedResponseLinkRecognizers.find(item->GetRecognizerType());
5613 if (iter == sortedResponseLinkRecognizers.end() || iter->second.empty()) {
5614 continue;
5615 }
5616 auto result = shouldBuiltInRecognizerParallelWithFunc(item, iter->second);
5617 if (result && item != result) {
5618 item->SetBridgeMode(true);
5619 result->AddBridgeObj(item);
5620 }
5621 }
5622 }
5623
ClearSubtreeLayoutAlgorithm(bool includeSelf,bool clearEntireTree)5624 void FrameNode::ClearSubtreeLayoutAlgorithm(bool includeSelf, bool clearEntireTree)
5625 {
5626 // return when reaches a child that has no layoutAlgorithm and no need to clear the entire tree
5627 if (!layoutAlgorithm_ && !clearEntireTree) {
5628 return;
5629 }
5630 // include Self might be false for the first ClearSubtreeLayoutAlgorithm enter,
5631 // but children should always include themselves
5632 if (includeSelf) {
5633 layoutAlgorithm_ = nullptr;
5634 }
5635 for (const auto& child : GetChildren()) {
5636 child->ClearSubtreeLayoutAlgorithm(true, clearEntireTree);
5637 }
5638 }
5639
OnSyncGeometryFrameFinish(const RectF & paintRect)5640 void FrameNode::OnSyncGeometryFrameFinish(const RectF& paintRect)
5641 {
5642 if (syncedFramePaintRect_.has_value() && syncedFramePaintRect_.value() != paintRect) {
5643 AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_GEOMETRY_CHANGE);
5644 if (AnimationUtils::IsImplicitAnimationOpen()) {
5645 AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_START_ANIMATION);
5646 }
5647 }
5648 syncedFramePaintRect_ = paintRect;
5649 }
5650
AddFrameNodeChangeInfoFlag(FrameNodeChangeInfoFlag changeFlag)5651 void FrameNode::AddFrameNodeChangeInfoFlag(FrameNodeChangeInfoFlag changeFlag)
5652 {
5653 if (changeInfoFlag_ == FRAME_NODE_CHANGE_INFO_NONE) {
5654 auto context = GetContext();
5655 CHECK_NULL_VOID(context);
5656 if (!context->AddChangedFrameNode(WeakClaim(this))) {
5657 return;
5658 }
5659 }
5660 changeInfoFlag_ = changeInfoFlag_ | changeFlag;
5661 }
5662
RegisterNodeChangeListener()5663 void FrameNode::RegisterNodeChangeListener()
5664 {
5665 auto context = GetContext();
5666 CHECK_NULL_VOID(context);
5667 context->AddFrameNodeChangeListener(WeakClaim(this));
5668 }
5669
UnregisterNodeChangeListener()5670 void FrameNode::UnregisterNodeChangeListener()
5671 {
5672 auto context = GetContext();
5673 CHECK_NULL_VOID(context);
5674 context->RemoveFrameNodeChangeListener(GetId());
5675 }
5676
ProcessFrameNodeChangeFlag()5677 void FrameNode::ProcessFrameNodeChangeFlag()
5678 {
5679 auto changeFlag = FRAME_NODE_CHANGE_INFO_NONE;
5680 auto parent = Claim(this);
5681 while (parent) {
5682 if (parent->GetChangeInfoFlag() != FRAME_NODE_CHANGE_INFO_NONE) {
5683 changeFlag = changeFlag | parent->GetChangeInfoFlag();
5684 }
5685 parent = parent->GetAncestorNodeOfFrame(true);
5686 }
5687 if (changeFlag == FRAME_NODE_CHANGE_INFO_NONE) {
5688 return;
5689 }
5690 auto pattern = GetPattern();
5691 if (pattern) {
5692 pattern->OnFrameNodeChanged(changeFlag);
5693 }
5694 }
5695
OnNodeTransformInfoUpdate(bool changed)5696 void FrameNode::OnNodeTransformInfoUpdate(bool changed)
5697 {
5698 if (!changed) {
5699 return;
5700 }
5701 AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_TRANSFORM_CHANGE);
5702 if (AnimationUtils::IsImplicitAnimationOpen()) {
5703 AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_START_ANIMATION);
5704 }
5705 }
5706
OnNodeTransitionInfoUpdate()5707 void FrameNode::OnNodeTransitionInfoUpdate()
5708 {
5709 AddFrameNodeChangeInfoFlag(FRAME_NODE_CHANGE_TRANSITION_START);
5710 }
5711
GetInspectorValue()5712 void FrameNode::GetInspectorValue()
5713 {
5714 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(OHOS_PLATFORM)
5715 if (GetTag() == V2::WEB_ETS_TAG) {
5716 UiSessionManager::GetInstance().WebTaskNumsChange(1);
5717 auto pattern = GetPattern<NG::WebPattern>();
5718 CHECK_NULL_VOID(pattern);
5719 auto cb = [](std::shared_ptr<JsonValue> value, int32_t webId) {
5720 UiSessionManager::GetInstance().AddValueForTree(webId, value->ToString());
5721 UiSessionManager::GetInstance().WebTaskNumsChange(-1);
5722 };
5723 pattern->GetAllWebAccessibilityNodeInfos(cb, GetId());
5724 }
5725 #endif
5726 UINode::GetInspectorValue();
5727 }
5728
NotifyWebPattern(bool isRegister)5729 void FrameNode::NotifyWebPattern(bool isRegister)
5730 {
5731 #if !defined(PREVIEW) && !defined(ACE_UNITTEST) && defined(WEB_SUPPORTED) && defined(OHOS_PLATFORM)
5732 if (GetTag() == V2::WEB_ETS_TAG) {
5733 auto pattern = GetPattern<NG::WebPattern>();
5734 CHECK_NULL_VOID(pattern);
5735 if (isRegister) {
5736 auto callback = [](int64_t accessibilityId, const std::string data) {
5737 UiSessionManager::GetInstance().ReportWebUnfocusEvent(accessibilityId, data);
5738 };
5739 pattern->RegisterTextBlurCallback(callback);
5740 } else {
5741 pattern->UnRegisterTextBlurCallback();
5742 }
5743 }
5744 #endif
5745 UINode::NotifyWebPattern(isRegister);
5746 }
5747
NotifyChange(int32_t index,int32_t count,int64_t id,NotificationType notificationType)5748 void FrameNode::NotifyChange(int32_t index, int32_t count, int64_t id, NotificationType notificationType)
5749 {
5750 int32_t updateFrom = CalcAbsPosition(index, id);
5751 auto pattern = GetPattern();
5752 switch (notificationType) {
5753 case NotificationType::START_CHANGE_POSITION:
5754 ChildrenUpdatedFrom(updateFrom);
5755 break;
5756 case NotificationType::END_CHANGE_POSITION:
5757 pattern->NotifyDataChange(updateFrom, count);
5758 break;
5759 case NotificationType::START_AND_END_CHANGE_POSITION:
5760 ChildrenUpdatedFrom(updateFrom);
5761 pattern->NotifyDataChange(updateFrom, count);
5762 break;
5763 default:
5764 break;
5765 }
5766 }
5767
5768 // for Grid refresh GridItems
ChildrenUpdatedFrom(int32_t index)5769 void FrameNode::ChildrenUpdatedFrom(int32_t index)
5770 {
5771 childrenUpdatedFrom_ = childrenUpdatedFrom_ >= 0 ? std::min(index, childrenUpdatedFrom_) : index;
5772 }
5773
GetWindowPatternType() const5774 uint32_t FrameNode::GetWindowPatternType() const
5775 {
5776 CHECK_NULL_RETURN(pattern_, 0);
5777 return pattern_->GetWindowPatternType();
5778 }
5779
ResetPredictNodes()5780 void FrameNode::ResetPredictNodes()
5781 {
5782 auto predictLayoutNode = std::move(predictLayoutNode_);
5783 for (auto& node : predictLayoutNode) {
5784 auto frameNode = node.Upgrade();
5785 if (frameNode && frameNode->isLayoutDirtyMarked_) {
5786 frameNode->isLayoutDirtyMarked_ = false;
5787 }
5788 }
5789 }
5790
SetJSCustomProperty(std::function<bool ()> func,std::function<std::string (const std::string &)> getFunc)5791 void FrameNode::SetJSCustomProperty(std::function<bool()> func, std::function<std::string(const std::string&)> getFunc)
5792 {
5793 bool result = func();
5794 if (IsCNode()) {
5795 return;
5796 }
5797 if (result) {
5798 customPropertyMap_[UPDATE_FLAG_KEY] = "1";
5799 }
5800 if (!getCustomProperty_) {
5801 getCustomProperty_ = getFunc;
5802 }
5803 }
5804
GetJSCustomProperty(const std::string & key,std::string & value)5805 bool FrameNode::GetJSCustomProperty(const std::string& key, std::string& value)
5806 {
5807 if (getCustomProperty_) {
5808 value = getCustomProperty_(key);
5809 return true;
5810 }
5811 return false;
5812 }
5813
GetCapiCustomProperty(const std::string & key,std::string & value)5814 bool FrameNode::GetCapiCustomProperty(const std::string& key, std::string& value)
5815 {
5816 if (!IsCNode()) {
5817 return false;
5818 }
5819 auto iter = customPropertyMap_.find(key);
5820 if (iter != customPropertyMap_.end()) {
5821 value = iter->second;
5822 return true;
5823 }
5824 return false;
5825 }
5826
AddCustomProperty(const std::string & key,const std::string & value)5827 void FrameNode::AddCustomProperty(const std::string& key, const std::string& value)
5828 {
5829 customPropertyMap_[key] = value;
5830 }
5831
RemoveCustomProperty(const std::string & key)5832 void FrameNode::RemoveCustomProperty(const std::string& key)
5833 {
5834 auto iter = customPropertyMap_.find(key);
5835 if (iter != customPropertyMap_.end()) {
5836 customPropertyMap_.erase(iter);
5837 }
5838 }
5839
GetCurrentPageRootNode()5840 RefPtr<UINode> FrameNode::GetCurrentPageRootNode()
5841 {
5842 auto pageNode = GetPageNode();
5843 CHECK_NULL_RETURN(pageNode, nullptr);
5844 auto jsView = pageNode->GetChildAtIndex(0);
5845 CHECK_NULL_RETURN(jsView, nullptr);
5846 if (jsView->GetTag() == V2::JS_VIEW_ETS_TAG) {
5847 auto rootNode = jsView->GetChildAtIndex(0);
5848 CHECK_NULL_RETURN(rootNode, nullptr);
5849 return rootNode;
5850 }
5851 return jsView;
5852 }
5853
GetActiveChildren()5854 std::list<RefPtr<FrameNode>> FrameNode::GetActiveChildren()
5855 {
5856 std::list<RefPtr<FrameNode>> list;
5857 for (int32_t i = 0; i < TotalChildCount(); i++) {
5858 auto child = GetFrameNodeChildByIndex(i, false, false);
5859 if (child->IsActive()) {
5860 list.emplace_back(Referenced::Claim(child));
5861 }
5862 }
5863 return list;
5864 }
5865
SetFrameNodeDestructorCallback(const std::function<void (int32_t)> && callback)5866 void FrameNode::SetFrameNodeDestructorCallback(const std::function<void(int32_t)>&& callback)
5867 {
5868 frameNodeDestructorCallback_ = callback;
5869 }
5870
FireFrameNodeDestructorCallback()5871 void FrameNode::FireFrameNodeDestructorCallback()
5872 {
5873 if (frameNodeDestructorCallback_) {
5874 frameNodeDestructorCallback_(GetId());
5875 }
5876 }
5877 } // namespace OHOS::Ace::NG
5878