1 /*
2 * Copyright (c) 2025 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "core/components_ng/pattern/xcomponent/xcomponent_pattern_v2.h"
17
18 #include "base/log/dump_log.h"
19 #include "base/utils/utils.h"
20 #include "core/accessibility/accessibility_session_adapter.h"
21 #include "core/components_ng/pattern/xcomponent/xcomponent_ext_surface_callback_client.h"
22
23 namespace OHOS::Ace::NG {
24
25 namespace {
BoolToString(bool value)26 inline std::string BoolToString(bool value)
27 {
28 return value ? "true" : "false";
29 }
30 } // namespace
31
XComponentPatternV2(XComponentType type,XComponentNodeType nodeType)32 XComponentPatternV2::XComponentPatternV2(XComponentType type, XComponentNodeType nodeType)
33 : XComponentPattern((nodeType == XComponentNodeType::CNODE) ? std::make_optional<std::string>("") : std::nullopt,
34 type, (nodeType == XComponentNodeType::CNODE) ? std::make_optional<std::string>("") : std::nullopt, nullptr)
35 {
36 nodeType_ = nodeType;
37 if (nodeType == XComponentNodeType::CNODE) {
38 isCNode_ = true;
39 }
40 }
41
SetSurfaceHolder(OH_ArkUI_SurfaceHolder * surfaceHolder)42 void XComponentPatternV2::SetSurfaceHolder(OH_ArkUI_SurfaceHolder* surfaceHolder)
43 {
44 surfaceHolder_ = surfaceHolder;
45 if (surfaceHolder_) {
46 surfaceHolder_->nativeWindow_ = reinterpret_cast<OHNativeWindow*>(nativeWindow_);
47 hasGotSurfaceHolder_ = true;
48 }
49 }
50
GetSurfaceHolder()51 OH_ArkUI_SurfaceHolder* XComponentPatternV2::GetSurfaceHolder()
52 {
53 return surfaceHolder_;
54 }
55
OnAttachToFrameNode()56 void XComponentPatternV2::OnAttachToFrameNode()
57 {
58 if (isCNode_) {
59 XComponentPattern::OnAttachToFrameNode();
60 return;
61 }
62 InitSurface();
63 InitNativeWindow(0.0, 0.0);
64 if (FrameReport::GetInstance().GetEnable()) {
65 FrameReport::GetInstance().EnableSelfRender();
66 }
67 }
68
OnAttachToMainTree()69 void XComponentPatternV2::OnAttachToMainTree()
70 {
71 UpdateUsesSuperMethod();
72 if (usesSuperMethod_) {
73 XComponentPattern::OnAttachToMainTree();
74 return;
75 }
76 isOnTree_ = true;
77 if (autoInitialize_) {
78 HandleSurfaceCreated();
79 }
80 }
81
BeforeSyncGeometryProperties(const DirtySwapConfig & config)82 void XComponentPatternV2::BeforeSyncGeometryProperties(const DirtySwapConfig& config)
83 {
84 UpdateUsesSuperMethod();
85 if (usesSuperMethod_) {
86 XComponentPattern::BeforeSyncGeometryProperties(config);
87 return;
88 }
89 CHECK_EQUAL_VOID(config.skipMeasure, true);
90 auto host = GetHost();
91 CHECK_NULL_VOID(host);
92 auto geometryNode = host->GetGeometryNode();
93 CHECK_NULL_VOID(geometryNode);
94 drawSize_ = geometryNode->GetContentSize();
95 if (!drawSize_.IsPositive()) {
96 TAG_LOGW(
97 AceLogTag::ACE_XCOMPONENT, "XComponent[%{public}s]'s size is not positive", GetId().c_str());
98 return;
99 }
100 localPosition_ = geometryNode->GetContentOffset();
101 if (IsSupportImageAnalyzerFeature()) {
102 UpdateAnalyzerUIConfig(geometryNode);
103 }
104 const auto& [offsetChanged, sizeChanged] = UpdateSurfaceRect();
105 HandleSurfaceChangeEvent(offsetChanged, sizeChanged, config.frameOffsetChange);
106 AddAfterLayoutTaskForExportTexture();
107 host->MarkNeedSyncRenderTree();
108 }
109
UpdateSurfaceRect()110 std::pair<bool, bool> XComponentPatternV2::UpdateSurfaceRect()
111 {
112 if (!drawSize_.IsPositive()) {
113 return { false, false };
114 }
115 auto preSurfaceSize = surfaceSize_;
116 auto preSurfaceOffset = surfaceOffset_;
117
118 surfaceSize_ = drawSize_;
119 surfaceOffset_ = localPosition_;
120 auto offsetChanged = preSurfaceOffset != surfaceOffset_;
121 auto sizeChanged = preSurfaceSize != surfaceSize_;
122 if (offsetChanged || sizeChanged) {
123 paintRect_ = AdjustPaintRect(
124 surfaceOffset_.GetX(), surfaceOffset_.GetY(), surfaceSize_.Width(), surfaceSize_.Height(), true);
125 }
126 return { offsetChanged, sizeChanged };
127 }
128
HandleSurfaceChangeEvent(bool offsetChanged,bool sizeChanged,bool frameOffsetChange)129 void XComponentPatternV2::HandleSurfaceChangeEvent(bool offsetChanged, bool sizeChanged, bool frameOffsetChange)
130 {
131 if (!drawSize_.IsPositive()) {
132 return;
133 }
134 if (sizeChanged) {
135 XComponentSizeChange(paintRect_);
136 }
137 if (renderContextForSurface_) {
138 renderContextForSurface_->SetBounds(
139 paintRect_.GetX(), paintRect_.GetY(), paintRect_.Width(), paintRect_.Height());
140 }
141 if (renderSurface_) {
142 renderSurface_->SetSurfaceDefaultSize(
143 static_cast<int32_t>(paintRect_.Width()), static_cast<int32_t>(paintRect_.Height()));
144 }
145 }
146
XComponentSizeChange(const RectF & surfaceRect)147 void XComponentPatternV2::XComponentSizeChange(const RectF& surfaceRect)
148 {
149 auto host = GetHost();
150 CHECK_NULL_VOID(host);
151 auto context = host->GetContextRefPtr();
152 CHECK_NULL_VOID(context);
153 auto viewScale = context->GetViewScale();
154 CHECK_NULL_VOID(renderSurface_);
155 auto width = surfaceRect.Width();
156 auto height = surfaceRect.Height();
157 needNotifySizeChanged_ = true;
158 renderSurface_->UpdateSurfaceSizeInUserData(
159 static_cast<uint32_t>(width), static_cast<uint32_t>(height));
160 renderSurface_->AdjustNativeWindowSize(
161 static_cast<uint32_t>(width * viewScale), static_cast<uint32_t>(height * viewScale));
162 OnSurfaceChanged(surfaceRect);
163 }
164
OnSurfaceChanged(const RectF & surfaceRect)165 void XComponentPatternV2::OnSurfaceChanged(const RectF& surfaceRect)
166 {
167 CHECK_RUN_ON(UI);
168 CHECK_NULL_VOID(surfaceHolder_);
169 CHECK_EQUAL_VOID(isInitialized_, false);
170 ACE_SCOPED_TRACE("XComponent[%s] surfaceHolder OnSurfaceChanged", GetId().c_str());
171 auto callbackList = surfaceHolder_->surfaceCallbackList_;
172 for (const auto& iter : callbackList) {
173 auto callback = iter->OnSurfaceChanged;
174 if (callback) {
175 callback(surfaceHolder_, surfaceRect.Width(), surfaceRect.Height());
176 }
177 }
178 needNotifySizeChanged_ = false;
179 }
180
OnDetachFromMainTree()181 void XComponentPatternV2::OnDetachFromMainTree()
182 {
183 UpdateUsesSuperMethod();
184 if (usesSuperMethod_) {
185 XComponentPattern::OnDetachFromMainTree();
186 return;
187 }
188 isOnTree_ = false;
189 if (autoInitialize_) {
190 HandleSurfaceDestroyed();
191 }
192 }
193
OnDetachFromFrameNode(FrameNode * frameNode)194 void XComponentPatternV2::OnDetachFromFrameNode(FrameNode* frameNode)
195 {
196 if (usesSuperMethod_) {
197 XComponentPattern::OnDetachFromFrameNode(frameNode);
198 return;
199 }
200 auto id = frameNode->GetId();
201 auto pipeline = frameNode->GetContextRefPtr();
202 CHECK_NULL_VOID(pipeline);
203 pipeline->RemoveWindowStateChangedCallback(id);
204 if (HasTransformHintChangedCallbackId()) {
205 pipeline->UnregisterTransformHintChangedCallback(transformHintChangedCallbackId_.value_or(-1));
206 }
207 if (FrameReport::GetInstance().GetEnable()) {
208 FrameReport::GetInstance().DisableSelfRender();
209 }
210 HandleSurfaceDestroyed();
211
212 CHECK_NULL_VOID(surfaceHolder_);
213 surfaceHolder_->nativeWindow_ = nullptr;
214 surfaceHolder_->node_ = nullptr;
215 }
216
InitSurface()217 void XComponentPatternV2::InitSurface()
218 {
219 auto host = GetHost();
220 CHECK_NULL_VOID(host);
221 auto renderContext = host->GetRenderContext();
222 CHECK_NULL_VOID(renderContext);
223
224 renderContext->SetClipToFrame(true);
225 renderContext->SetClipToBounds(true);
226 renderSurface_ = RenderSurface::Create();
227 renderSurface_->SetInstanceId(GetHostInstanceId());
228 if (type_ == XComponentType::SURFACE) {
229 InitializeRenderContext();
230 renderSurface_->SetRenderContext(renderContextForSurface_);
231 } else if (type_ == XComponentType::TEXTURE) {
232 renderSurface_->SetRenderContext(renderContext);
233 renderSurface_->SetIsTexture(true);
234 renderContext->OnNodeNameUpdate(GetId());
235 }
236 renderSurface_->InitSurface();
237 renderSurface_->UpdateSurfaceConfig();
238 if (type_ == XComponentType::TEXTURE) {
239 renderSurface_->RegisterBufferCallback();
240 }
241 surfaceId_ = renderSurface_->GetUniqueId();
242
243 UpdateTransformHint();
244 }
245
HandleSurfaceCreated()246 int32_t XComponentPatternV2::HandleSurfaceCreated()
247 {
248 CHECK_EQUAL_RETURN(isInitialized_, true, ERROR_CODE_XCOMPONENT_STATE_INVALID);
249 CHECK_NULL_RETURN(renderSurface_, ERROR_CODE_PARAM_INVALID);
250 renderSurface_->RegisterSurface();
251 surfaceId_ = renderSurface_->GetUniqueId();
252 isInitialized_ = true;
253 if (surfaceHolder_) {
254 auto callbackList = surfaceHolder_->surfaceCallbackList_;
255 TAG_LOGI(AceLogTag::ACE_XCOMPONENT, "XComponent[%{public}s] surfaceHolder OnSurfaceCreated", GetId().c_str());
256 ACE_SCOPED_TRACE("XComponent[%s] surfaceHolder OnSurfaceCreated", GetId().c_str());
257 for (const auto& iter : callbackList) {
258 auto callback = iter->OnSurfaceCreated;
259 if (callback) {
260 callback(surfaceHolder_);
261 }
262 }
263 }
264 if (needNotifySizeChanged_) {
265 OnSurfaceChanged(paintRect_);
266 }
267 return ERROR_CODE_NO_ERROR;
268 }
269
HandleSurfaceDestroyed()270 int32_t XComponentPatternV2::HandleSurfaceDestroyed()
271 {
272 CHECK_EQUAL_RETURN(isInitialized_, false, ERROR_CODE_XCOMPONENT_STATE_INVALID);
273 isInitialized_ = false;
274 CHECK_NULL_RETURN(renderSurface_, ERROR_CODE_PARAM_INVALID);
275 renderSurface_->ReleaseSurfaceBuffers();
276 renderSurface_->UnregisterSurface();
277 if (surfaceHolder_) {
278 auto callbackList = surfaceHolder_->surfaceCallbackList_;
279 TAG_LOGI(AceLogTag::ACE_XCOMPONENT, "XComponent[%{public}s] surfaceHolder OnSurfaceDestroyed", GetId().c_str());
280 ACE_SCOPED_TRACE("XComponent[%s] surfaceHolder OnSurfaceDestroyed", GetId().c_str());
281 for (const auto& iter : callbackList) {
282 auto callback = iter->OnSurfaceDestroyed;
283 if (callback) {
284 callback(surfaceHolder_);
285 }
286 }
287 }
288 return ERROR_CODE_NO_ERROR;
289 }
290
Initialize()291 int32_t XComponentPatternV2::Initialize()
292 {
293 CHECK_EQUAL_RETURN(usesSuperMethod_, true, ERROR_CODE_PARAM_INVALID);
294 isLifecycleInterfaceCalled_ = true;
295 return HandleSurfaceCreated();
296 }
297
Finalize()298 int32_t XComponentPatternV2::Finalize()
299 {
300 CHECK_EQUAL_RETURN(usesSuperMethod_, true, ERROR_CODE_PARAM_INVALID);
301 isLifecycleInterfaceCalled_ = true;
302 return HandleSurfaceDestroyed();
303 }
304
SetAutoInitialize(bool autoInitialize)305 int32_t XComponentPatternV2::SetAutoInitialize(bool autoInitialize)
306 {
307 CHECK_EQUAL_RETURN(usesSuperMethod_, true, ERROR_CODE_PARAM_INVALID);
308 isLifecycleInterfaceCalled_ = true;
309 autoInitialize_ = autoInitialize;
310 return ERROR_CODE_NO_ERROR;
311 }
312
IsInitialized(bool & isInitialized)313 int32_t XComponentPatternV2::IsInitialized(bool& isInitialized)
314 {
315 CHECK_EQUAL_RETURN(usesSuperMethod_, true, ERROR_CODE_PARAM_INVALID);
316 isLifecycleInterfaceCalled_ = true;
317 isInitialized = isInitialized_;
318 return ERROR_CODE_NO_ERROR;
319 }
320
OnWindowHide()321 void XComponentPatternV2::OnWindowHide()
322 {
323 if (usesSuperMethod_) {
324 XComponentPattern::OnWindowHide();
325 return;
326 }
327 CHECK_EQUAL_VOID(hasReleasedSurface_, true);
328 if (renderSurface_) {
329 renderSurface_->OnWindowStateChange(false);
330 }
331 hasReleasedSurface_ = true;
332 }
333
OnWindowShow()334 void XComponentPatternV2::OnWindowShow()
335 {
336 if (usesSuperMethod_) {
337 XComponentPattern::OnWindowShow();
338 return;
339 }
340 CHECK_EQUAL_VOID(hasReleasedSurface_, false);
341 if (renderSurface_) {
342 renderSurface_->OnWindowStateChange(true);
343 }
344 hasReleasedSurface_ = false;
345 }
346
OnRebuildFrame()347 void XComponentPatternV2::OnRebuildFrame()
348 {
349 if (usesSuperMethod_) {
350 XComponentPattern::OnRebuildFrame();
351 return;
352 }
353 if (type_ != XComponentType::SURFACE) {
354 return;
355 }
356 if (!renderSurface_->IsSurfaceValid()) {
357 return;
358 }
359 auto host = GetHost();
360 CHECK_NULL_VOID(host);
361 auto renderContext = host->GetRenderContext();
362 CHECK_NULL_VOID(renderContext);
363 CHECK_NULL_VOID(renderContextForSurface_);
364 renderContext->AddChild(renderContextForSurface_, 0);
365 }
366
InitializeRenderContext()367 void XComponentPatternV2::InitializeRenderContext()
368 {
369 renderContextForSurface_ = RenderContext::Create();
370 RenderContext::ContextParam param = { RenderContext::ContextType::HARDWARE_SURFACE,
371 GetId() + "Surface", RenderContext::PatternType::XCOM };
372 renderContextForSurface_->InitContext(false, param);
373 renderContextForSurface_->UpdateBackgroundColor(Color::BLACK);
374 }
375
OnModifyDone()376 void XComponentPatternV2::OnModifyDone()
377 {
378 if (usesSuperMethod_) {
379 XComponentPattern::OnModifyDone();
380 return;
381 }
382 Pattern::OnModifyDone();
383 auto host = GetHost();
384 CHECK_NULL_VOID(host);
385 auto renderContext = host->GetRenderContext();
386 CHECK_NULL_VOID(renderContext);
387 CHECK_NULL_VOID(renderContextForSurface_);
388 auto bkColor = renderContext->GetBackgroundColor();
389 if (bkColor.has_value()) {
390 bool isTransparent = bkColor.value().GetAlpha() < UINT8_MAX;
391 renderContextForSurface_->UpdateBackgroundColor(isTransparent ? Color::TRANSPARENT : bkColor.value());
392 } else {
393 renderContextForSurface_->UpdateBackgroundColor(Color::BLACK);
394 }
395 }
396
DumpInfo()397 void XComponentPatternV2::DumpInfo()
398 {
399 if (usesSuperMethod_) {
400 XComponentPattern::DumpInfo();
401 return;
402 }
403 DumpLog::GetInstance().AddDesc(std::string("autoInitialize: ").append(BoolToString(autoInitialize_)));
404 DumpLog::GetInstance().AddDesc(std::string("isInitialized: ").append(BoolToString(isInitialized_)));
405 DumpLog::GetInstance().AddDesc(
406 std::string("xcomponentNodeType: ").append(XComponentPattern::XComponentNodeTypeToString(nodeType_)));
407 DumpLog::GetInstance().AddDesc(
408 std::string("xcomponentType: ").append(XComponentPattern::XComponentTypeToString(type_)));
409 DumpLog::GetInstance().AddDesc(std::string("surfaceId: ").append(surfaceId_));
410 DumpLog::GetInstance().AddDesc(std::string("surfaceRect: ").append(paintRect_.ToString()));
411 }
412 } // namespace OHOS::Ace::NG