1 /*
2 * Copyright (c) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "core/components_ng/pattern/node_container/node_container_pattern.h"
17
18 #include "core/common/builder_util.h"
19 #include "core/pipeline_ng/pipeline_context.h"
20 #include "core/pipeline/base/element_register.h"
21
22 namespace OHOS::Ace::NG {
23 namespace {
CheckBeforeAddNode(const RefPtr<UINode> & hostNode,const RefPtr<UINode> & newNode)24 bool CheckBeforeAddNode(const RefPtr<UINode>& hostNode, const RefPtr<UINode>& newNode)
25 {
26 CHECK_NULL_RETURN(hostNode, false);
27 CHECK_NULL_RETURN(newNode, true);
28 if (!(newNode->IsArkTsFrameNode()) && !newNode->GetIsRootBuilderNode()) {
29 TAG_LOGW(AceLogTag::ACE_NODE_CONTAINER, "Cannot return node created by declarative UI function");
30 return false;
31 }
32 auto parent = newNode->GetParent();
33 if (parent && parent != hostNode) {
34 TAG_LOGF(AceLogTag::ACE_NODE_CONTAINER,
35 "Add [id:%{public}d][tag:%{public}s] to [id:%{public}d][tag:%{public}s] with previous parent "
36 "[id:%{public}d][tag:%{public}s]",
37 newNode->GetId(), newNode->GetTag().c_str(), hostNode->GetId(), hostNode->GetTag().c_str(), parent->GetId(),
38 parent->GetTag().c_str());
39 }
40 return true;
41 }
42 } // namespace
43
RemakeNode()44 void NodeContainerPattern::RemakeNode()
45 {
46 auto host = GetHost();
47 CHECK_NULL_VOID(host);
48 auto newNode = FireMakeFunction();
49 AddBaseNode(newNode);
50 }
51
AddBaseNode(const RefPtr<UINode> & newNode)52 void NodeContainerPattern::AddBaseNode(const RefPtr<UINode>& newNode)
53 {
54 auto host = GetHost();
55 CHECK_NULL_VOID(host);
56 auto oldChild = host->GetChildAtIndex(0);
57 if ((!oldChild && !newNode) || (oldChild && oldChild == newNode)) {
58 return;
59 }
60 host->RemoveChildAtIndex(0);
61 BuilderUtils::RemoveBuilderFromParent(host, oldChild);
62 if (newNode) {
63 CHECK_NULL_VOID(CheckBeforeAddNode(host, newNode));
64 host->AddChild(newNode, 0);
65 BuilderUtils::AddBuilderToParent(host, newNode);
66 newNode->UpdateGeometryTransition();
67 }
68 OnAddBaseNode();
69 host->MarkNeedFrameFlushDirty(NG::PROPERTY_UPDATE_MEASURE);
70 }
71
CleanChild()72 void NodeContainerPattern::CleanChild()
73 {
74 auto host = GetHost();
75 CHECK_NULL_VOID(host);
76 host->RemoveChildAtIndex(0);
77 host->MarkNeedFrameFlushDirty(NG::PROPERTY_UPDATE_MEASURE);
78 }
79
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & config)80 bool NodeContainerPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& config)
81 {
82 if (config.skipMeasure && config.skipLayout) {
83 return false;
84 }
85 auto host = GetHost();
86 CHECK_NULL_RETURN(host, false);
87 auto context = host->GetContext();
88 CHECK_NULL_RETURN(context, false);
89 if (config.frameSizeChange) {
90 auto geometryNode = dirty->GetGeometryNode();
91 auto size = geometryNode->GetFrameSize();
92 context->AddAfterLayoutTask([weak = WeakClaim(this), size]() {
93 auto pattern = weak.Upgrade();
94 CHECK_NULL_VOID(pattern);
95 pattern->FireOnResize(size);
96 });
97 }
98 if (surfaceId_ != 0U && !exportTextureNode_.Invalid()) {
99 context->AddAfterLayoutTask([weak = WeakClaim(this)]() {
100 auto pattern = weak.Upgrade();
101 CHECK_NULL_VOID(pattern);
102 auto host = pattern->GetHost();
103 auto ret = pattern->HandleTextureExport(false, Referenced::RawPtr(host));
104 if (!ret) {
105 TAG_LOGW(AceLogTag::ACE_NODE_CONTAINER, "DoTextureExport fail");
106 }
107 });
108 }
109 return false;
110 }
111
HandleTextureExport(bool isStop,FrameNode * frameNode)112 bool NodeContainerPattern::HandleTextureExport(bool isStop, FrameNode* frameNode)
113 {
114 auto exportTextureNode = GetExportTextureNode();
115 CHECK_NULL_RETURN(exportTextureNode, false);
116 auto exportTextureRenderContext = exportTextureNode->GetRenderContext();
117 CHECK_NULL_RETURN(exportTextureRenderContext, false);
118 if (frameNode) {
119 auto renderContext = frameNode->GetRenderContext();
120 CHECK_NULL_RETURN(renderContext, false);
121 renderContext->SetIsNeedRebuildRSTree(isStop);
122 }
123 auto elementRegister = ElementRegister::GetInstance();
124 if (isStop) {
125 if (elementRegister) {
126 elementRegister->UnregisterEmbedNode(surfaceId_, WeakPtr(exportTextureNode));
127 }
128 return exportTextureRenderContext->StopTextureExport();
129 }
130 if (elementRegister) {
131 elementRegister->RegisterEmbedNode(surfaceId_, WeakPtr(exportTextureNode));
132 }
133 return exportTextureRenderContext->DoTextureExport(surfaceId_);
134 }
135
OnDetachFromFrameNode(FrameNode * frameNode)136 void NodeContainerPattern::OnDetachFromFrameNode(FrameNode* frameNode)
137 {
138 HandleTextureExport(true, frameNode);
139 }
140
GetExportTextureNode() const141 RefPtr<FrameNode> NodeContainerPattern::GetExportTextureNode() const
142 {
143 auto exportTextureNode = exportTextureNode_.Upgrade();
144 CHECK_NULL_RETURN(exportTextureNode, nullptr);
145 auto exportTextureFrameNode = DynamicCast<FrameNode>(exportTextureNode);
146 while (exportTextureNode && !exportTextureFrameNode) {
147 exportTextureNode = exportTextureNode->GetFirstChild();
148 exportTextureFrameNode = DynamicCast<FrameNode>(exportTextureNode);
149 }
150 return exportTextureFrameNode;
151 }
152
ResetExportTextureInfo()153 void NodeContainerPattern::ResetExportTextureInfo()
154 {
155 surfaceId_ = 0U;
156 exportTextureNode_.Reset();
157 }
158
SetExportTextureInfoIfNeeded()159 void NodeContainerPattern::SetExportTextureInfoIfNeeded()
160 {
161 ResetExportTextureInfo();
162 auto host = GetHost();
163 CHECK_NULL_VOID(host);
164 auto viewNode = host->GetChildAtIndex(0);
165 CHECK_NULL_VOID(viewNode);
166 if (!viewNode->IsNeedExportTexture()) {
167 return;
168 }
169 auto parent = host->GetAncestorNodeOfFrame(false);
170 if (parent) {
171 auto nodeContainer = parent->GetNodeContainer();
172 if (nodeContainer) {
173 auto parentViewNode = nodeContainer->GetChildAtIndex(0);
174 CHECK_NULL_VOID(parentViewNode);
175 auto parnetExportTextureInfo = parentViewNode->GetExportTextureInfo();
176 if (parnetExportTextureInfo &&
177 parnetExportTextureInfo->GetCurrentRenderType() == NodeRenderType::RENDER_TYPE_TEXTURE) {
178 return;
179 }
180 }
181 }
182 auto exportTextureInfo = viewNode->GetExportTextureInfo();
183 exportTextureNode_ = viewNode;
184 surfaceId_ = StringUtils::StringToLongUint(exportTextureInfo->GetSurfaceId());
185 }
186
OnAddBaseNode()187 void NodeContainerPattern::OnAddBaseNode()
188 {
189 auto host = GetHost();
190 HandleTextureExport(true, Referenced::RawPtr(host));
191 SetExportTextureInfoIfNeeded();
192 }
193
OnMountToParentDone()194 void NodeContainerPattern::OnMountToParentDone()
195 {
196 SetExportTextureInfoIfNeeded();
197 }
198
GetNodeContainerEventHub()199 RefPtr<NodeContainerEventHub> NodeContainerPattern::GetNodeContainerEventHub()
200 {
201 auto frameNode = ViewStackProcessor::GetInstance()->GetMainFrameNode();
202 if (frameNode) {
203 return frameNode->GetOrCreateEventHub<NodeContainerEventHub>();
204 }
205 return nullptr;
206 }
207
FireOnWillBind(int32_t containerId)208 void NodeContainerPattern::FireOnWillBind(int32_t containerId)
209 {
210 auto nodeContainerEventHub = GetNodeContainerEventHub();
211 if (nodeContainerEventHub) {
212 nodeContainerEventHub->FireOnWillBind(containerId);
213 }
214 }
215
FireOnWillUnbind(int32_t containerId)216 void NodeContainerPattern::FireOnWillUnbind(int32_t containerId)
217 {
218 auto nodeContainerEventHub = GetNodeContainerEventHub();
219 if (nodeContainerEventHub) {
220 nodeContainerEventHub->FireOnWillUnbind(containerId);
221 }
222 }
223
FireOnBind(int32_t containerId)224 void NodeContainerPattern::FireOnBind(int32_t containerId)
225 {
226 auto nodeContainerEventHub = GetNodeContainerEventHub();
227 if (nodeContainerEventHub) {
228 nodeContainerEventHub->FireOnBind(containerId);
229 }
230 }
231
FireOnUnbind(int32_t containerId)232 void NodeContainerPattern::FireOnUnbind(int32_t containerId)
233 {
234 auto nodeContainerEventHub = GetNodeContainerEventHub();
235 if (nodeContainerEventHub) {
236 nodeContainerEventHub->FireOnUnbind(containerId);
237 }
238 }
239 } // namespace OHOS::Ace::NG
240