• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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