1 /*
2 * Copyright (c) 2021-2022 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/pipeline/base/render_element.h"
17 #include <string>
18
19 #include "base/log/log.h"
20 #include "base/utils/string_utils.h"
21 #include "base/utils/utils.h"
22 #include "core/accessibility/accessibility_manager.h"
23 #include "core/components/focus_animation/render_focus_animation.h"
24 #include "core/components/shadow/render_shadow.h"
25 #include "core/components_v2/inspector/inspector_composed_element.h"
26 #include "core/event/ace_event_helper.h"
27 #include "core/pipeline/base/composed_element.h"
28 #include "core/pipeline/base/render_component.h"
29
30 namespace OHOS::Ace {
31
RenderElement()32 RenderElement::RenderElement()
33 {
34 type_ = RENDER_ELEMENT;
35 }
36
~RenderElement()37 RenderElement::~RenderElement() {}
38
Prepare(const WeakPtr<Element> & parent)39 void RenderElement::Prepare(const WeakPtr<Element>& parent)
40 {
41 if (!renderNode_) {
42 renderNode_ = CreateRenderNode();
43 }
44 if (renderNode_) {
45 renderNode_->SyncRSNodeBoundary(component_->IsHeadComponent(), component_->IsTailComponent(), component_);
46 SetAccessibilityNode(parent);
47 renderNode_->Attach(context_);
48 }
49 // register on focus move callback
50 auto focusItem = AceType::DynamicCast<FocusNode>(this);
51 if (focusItem) {
52 focusItem->SetFocusMoveCallback([weak = AceType::WeakClaim(this)] {
53 auto element = weak.Upgrade();
54 if (element && element->renderNode_) {
55 element->renderNode_->MoveWhenOutOfViewPort(true);
56 }
57 });
58 }
59 nodeMounted_ = true;
60
61 int32_t restoreId = component_->GetRestoreId();
62 if (restoreId >= 0) {
63 auto context = context_.Upgrade();
64 if (context) {
65 // store distribute node
66 context->StoreNode(restoreId, AceType::WeakClaim(this));
67 // restore distribute node info
68 if (renderNode_) {
69 renderNode_->SetRestoreInfo(context->GetRestoreInfo(restoreId));
70 }
71 }
72 }
73 }
74
SetAccessibilityNode(const WeakPtr<Element> & parent)75 void RenderElement::SetAccessibilityNode(const WeakPtr<Element>& parent)
76 {
77 auto context = context_.Upgrade();
78 if (!context) {
79 LOGE("SetAccessibilityNode context is null");
80 return;
81 }
82 bool ignoreAccessibility = false;
83 if (component_) {
84 ignoreAccessibility = component_->IsIgnoreInspector();
85 }
86 auto parentNode = parent.Upgrade();
87 while (parentNode) {
88 if (!parentNode->IsAutoAccessibility()) {
89 break;
90 }
91 if (context->GetIsDeclarative()) {
92 if (ignoreAccessibility || parentNode->IsIgnoreInspector()) {
93 break;
94 }
95 auto composedElement = AceType::DynamicCast<V2::InspectorComposedElement>(parentNode);
96 if (composedElement) {
97 composeId_ = std::to_string(composedElement->GetInspectorId());
98 SetAccessibilityNodeById(composeId_);
99 renderNode_->SetInspectorNode(composedElement);
100 break;
101 } else {
102 parentNode = parentNode->GetElementParent().Upgrade();
103 }
104 continue;
105 }
106 auto composedElement = AceType::DynamicCast<ComposedElement>(parentNode);
107 if (composedElement) {
108 composeId_ = composedElement->GetId();
109 SetAccessibilityNodeById(composeId_);
110 break;
111 } else {
112 parentNode = parentNode->GetElementParent().Upgrade();
113 }
114 }
115 }
116
SetAccessibilityNodeById(const ComposeId & id)117 void RenderElement::SetAccessibilityNodeById(const ComposeId& id)
118 {
119 auto context = context_.Upgrade();
120 if (!context) {
121 LOGE("SetAccessibilityNodeById context is null");
122 return;
123 }
124 if (!renderNode_) {
125 LOGE("RenderElement don't have a render node");
126 return;
127 }
128 auto accessibilityManager = context->GetAccessibilityManager();
129 if (!accessibilityManager) {
130 LOGE("SetAccessibilityNode accessibilityManager is null");
131 return;
132 }
133 auto nodeId = StringUtils::StringToInt(id);
134 auto accessibilityNode = accessibilityManager->GetAccessibilityNodeById(nodeId);
135 if (accessibilityNode) {
136 renderNode_->SetAccessibilityNode(accessibilityNode);
137 }
138 }
139
UpdateAccessibilityNode()140 void RenderElement::UpdateAccessibilityNode()
141 {
142 auto context = context_.Upgrade();
143 if (!context) {
144 LOGE("UpdateAccessibilityNode context is null");
145 return;
146 }
147 if (context->GetIsDeclarative()) {
148 LOGD("UpdateAccessibilityNode context is declarative");
149 return;
150 }
151 // fetch new composedId from component.
152 ComposeId updateId;
153 auto component = component_;
154 while (component) {
155 auto composedNode = AceType::DynamicCast<ComposedComponent>(component);
156 if (composedNode) {
157 updateId = composedNode->GetId();
158 break;
159 }
160 component = component->GetParent().Upgrade();
161 }
162
163 // Update new composedId to renderNode.
164 if (!updateId.empty() && updateId != composeId_) {
165 SetAccessibilityNodeById(updateId);
166 LOGD("Update ComposeId from %s to %s", composeId_.c_str(), updateId.c_str());
167 composeId_ = updateId;
168 }
169 }
170
Apply(const RefPtr<Element> & child)171 void RenderElement::Apply(const RefPtr<Element>& child)
172 {
173 if (!child) {
174 LOGE("Element child is null");
175 return;
176 }
177
178 if (child->GetType() == RENDER_ELEMENT) {
179 // Directly attach the RenderNode if child is RenderElement.
180 ApplyRenderChild(AceType::DynamicCast<RenderElement>(child));
181 } else if (child->GetType() == COMPOSED_ELEMENT) {
182 // If child is ComposedElement, just set apply function.
183 RefPtr<ComposedElement> composeChild = AceType::DynamicCast<ComposedElement>(child);
184 if (composeChild) {
185 composeChild->ApplyComposed([weak = AceType::WeakClaim(this)](const RefPtr<RenderElement>& renderChild) {
186 auto renderElement = weak.Upgrade();
187 if (renderElement) {
188 renderElement->ApplyRenderChild(renderChild);
189 }
190 });
191 }
192 }
193 }
194
ApplyRenderChild(const RefPtr<RenderElement> & renderChild)195 void RenderElement::ApplyRenderChild(const RefPtr<RenderElement>& renderChild)
196 {
197 if (!renderChild) {
198 LOGW("Invalid render child");
199 return;
200 }
201
202 if (!renderNode_) {
203 LOGE("RenderElement don't have a render node");
204 return;
205 }
206
207 renderNode_->AddChild(renderChild->GetRenderNode(), renderChild->GetRenderSlot());
208 }
209
Update()210 void RenderElement::Update()
211 {
212 if (renderNode_ != nullptr) {
213 UpdateAccessibilityNode();
214 renderNode_->ProcessExternalRSNode(component_);
215 renderNode_->UpdateAll(component_);
216 if (component_ && nodeMounted_) {
217 SetElementId(component_->GetElementId());
218 if (!component_->GetAppearEventMarker().IsEmpty()) {
219 auto appearCallback = AceAsyncEvent<void()>::Create(component_->GetAppearEventMarker(), context_);
220 appearCallback();
221 }
222 if (!component_->GetDisappearEventMarker().IsEmpty()) {
223 disappearCallback_ = AceAsyncEvent<void()>::Create(component_->GetDisappearEventMarker(), context_);
224 } else {
225 disappearCallback_ = nullptr;
226 }
227 nodeMounted_ = false;
228 }
229 }
230 }
231
CreateRenderNode()232 RefPtr<RenderNode> RenderElement::CreateRenderNode()
233 {
234 RefPtr<RenderComponent> renderComponent = AceType::DynamicCast<RenderComponent>(component_);
235 if (renderComponent) {
236 auto renderNode = GetCachedRenderNode();
237 if (renderNode) {
238 LOGD("RenderElement Using Cache RenderNode");
239 return renderNode;
240 } else {
241 return renderComponent->CreateRenderNode();
242 }
243 }
244 return nullptr;
245 }
246
Detached()247 void RenderElement::Detached()
248 {
249 Deactivate();
250 if (renderNode_) {
251 renderNode_ = nullptr;
252 }
253 if (disappearCallback_) {
254 disappearCallback_();
255 }
256 }
257
Deactivate()258 void RenderElement::Deactivate()
259 {
260 UmountRender();
261 }
262
UmountRender()263 void RenderElement::UmountRender()
264 {
265 if (renderNode_) {
266 auto focusAnimation = AceType::DynamicCast<RenderFocusAnimation>(renderNode_);
267 auto context = context_.Upgrade();
268 if (focusAnimation) {
269 if (context) {
270 focusAnimation->IsRoot() ? context->PopRootFocusAnimation() : context->PopFocusAnimation();
271 }
272 }
273
274 auto shadow = AceType::DynamicCast<RenderShadow>(renderNode_);
275 if (shadow) {
276 if (context) {
277 context->PopShadow();
278 }
279 }
280 if (renderNode_->NeedWindowBlur()) {
281 renderNode_->MarkNeedWindowBlur(false);
282 }
283 renderNode_->Unmount();
284 }
285 }
286
UpdateChild(const RefPtr<Element> & child,const RefPtr<Component> & newComponent)287 RefPtr<Element> RenderElement::UpdateChild(const RefPtr<Element>& child, const RefPtr<Component>& newComponent)
288 {
289 return UpdateChildWithSlot(child, newComponent, DEFAULT_ELEMENT_SLOT, DEFAULT_RENDER_SLOT);
290 }
291
292 } // namespace OHOS::Ace
293