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