• 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_ROOT_ACCESSIBILITY_FOCUS_PAINT_NODE_PATTERN_H
17 #define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_ROOT_ACCESSIBILITY_FOCUS_PAINT_NODE_PATTERN_H
18 
19 #include "core/components_ng/pattern/overlay/accessibility_focus_paint_node_layout_algorithm.h"
20 #include "core/components_ng/pattern/pattern.h"
21 #include "core/components_ng/render/render_context.h"
22 #include "core/pipeline_ng/pipeline_context.h"
23 
24 #define CENTER_DIVISOR 2
25 
26 namespace OHOS::Ace::NG {
27 
28 class AccessibilityFocusPaintNodePattern : public Pattern {
29     DECLARE_ACE_TYPE(AccessibilityFocusPaintNodePattern, Pattern);
30 
31 public:
AccessibilityFocusPaintNodePattern(const WeakPtr<FrameNode> & frameNode)32     AccessibilityFocusPaintNodePattern(const WeakPtr<FrameNode>& frameNode) : focusNode_(frameNode) {};
33     ~AccessibilityFocusPaintNodePattern() override = default;
CreateLayoutAlgorithm()34     RefPtr<LayoutAlgorithm> CreateLayoutAlgorithm() override
35     {
36         return MakeRefPtr<AccessibilityFocusPaintLayoutAlgorithm>();
37     }
38 
UpdateFocusNode(const WeakPtr<FrameNode> & frameNode)39     void UpdateFocusNode(const WeakPtr<FrameNode>& frameNode)
40     {
41         RefPtr<NG::FrameNode> targetNode = frameNode.Upgrade();
42         CHECK_NULL_VOID(targetNode);
43         ACE_SCOPED_TRACE("AccessibilityFocusPainNode UpdateFocusNode[%s]", targetNode->GetTag().c_str());
44         focusNode_ = targetNode;
45         auto host = GetHost();
46         CHECK_NULL_VOID(host);
47         targetNode->SetPaintNode(host);
48     }
49 
UpdateRootNode(const WeakPtr<UINode> & frameNode)50     void UpdateRootNode(const WeakPtr<UINode>& frameNode)
51     {
52         rootNode_ = frameNode;
53     }
54 
UpdateRenderWithFocusNode()55     void UpdateRenderWithFocusNode()
56     {
57         RefPtr<NG::FrameNode> focusNode = focusNode_.Upgrade();
58         CHECK_NULL_VOID(focusNode);
59         auto host = GetHost();
60         CHECK_NULL_VOID(host);
61         ChangePaintNodeLayoutInner(focusNode, host, 0, 0);
62     }
63 
SetPosition(const NG::OffsetF & offset,const RefPtr<NG::FrameNode> & frameNode)64     void SetPosition(const NG::OffsetF& offset, const RefPtr<NG::FrameNode>& frameNode)
65     {
66         CHECK_NULL_VOID(frameNode);
67         auto renderContext = frameNode->GetRenderContext();
68         CHECK_NULL_VOID(renderContext);
69         renderContext->UpdatePosition(
70             { Dimension(offset.GetX(), DimensionUnit::PX), Dimension(offset.GetY(), DimensionUnit::PX) });
71     }
72 
ChangeSize(float width,float height,const RefPtr<NG::FrameNode> & frameNode)73     void ChangeSize(float width, float height, const RefPtr<NG::FrameNode>& frameNode)
74     {
75         CHECK_NULL_VOID(frameNode);
76         NG::CalcSize idealSize = { NG::CalcLength(width), NG::CalcLength(height) };
77         NG::MeasureProperty layoutConstraint;
78         layoutConstraint.selfIdealSize = idealSize;
79         layoutConstraint.maxSize = idealSize;
80         frameNode->UpdateLayoutConstraint(layoutConstraint);
81     }
82 
ChangelRotate(float degree,const RefPtr<NG::FrameNode> & frameNode)83     void ChangelRotate(float degree, const RefPtr<NG::FrameNode>& frameNode)
84     {
85         auto value = NG::Vector5F(0, 0, 1, degree, 0);
86         CHECK_NULL_VOID(frameNode);
87         auto context = frameNode->GetRenderContext();
88         CHECK_NULL_VOID(context);
89         context->UpdateTransformRotate(value);
90     }
91 
GetPaintRectCenter(const RefPtr<NG::FrameNode> & focusNode)92     OffsetF GetPaintRectCenter(const RefPtr<NG::FrameNode>& focusNode)
93     {
94         CHECK_NULL_RETURN(focusNode, OffsetF());
95         auto context = focusNode->GetRenderContext();
96         CHECK_NULL_RETURN(context, OffsetF());
97         auto paintRect = context->GetPaintRectWithoutTransform();
98         auto offset = paintRect.GetOffset();
99         PointF pointNode(offset.GetX() + paintRect.Width() / CENTER_DIVISOR,
100             offset.GetY() + paintRect.Height() / CENTER_DIVISOR);
101         context->GetPointTransformRotate(pointNode);
102         auto parent = focusNode->GetAncestorNodeOfFrame(true);
103         while (parent) {
104             auto renderContext = parent->GetRenderContext();
105             CHECK_NULL_RETURN(renderContext, OffsetF());
106             offset = renderContext->GetPaintRectWithoutTransform().GetOffset();
107             pointNode.SetX(offset.GetX() + pointNode.GetX());
108             pointNode.SetY(offset.GetY() + pointNode.GetY());
109             renderContext->GetPointTransformRotate(pointNode);
110             parent = parent->GetAncestorNodeOfFrame(true);
111         }
112         return OffsetF(pointNode.GetX(), pointNode.GetY());
113     }
114 
IntersectRectF(RectF & finalRect,RectF parentRect)115     void IntersectRectF(RectF& finalRect, RectF parentRect)
116     {
117         auto left = std::max(finalRect.GetX(), parentRect.GetX());
118         auto top = std::max(finalRect.GetY(), parentRect.GetY());
119         auto right = std::min(finalRect.Width() + finalRect.GetX(), parentRect.Width() + parentRect.GetX());
120         auto bottom = std::min(finalRect.Height() + finalRect.GetY(), parentRect.Height() + parentRect.GetY());
121         if (left < right && top < bottom) {
122             finalRect = RectF(left, top, right - left, bottom - top);
123         } else {
124             finalRect = RectF();
125         }
126     }
127 
IsScrollable(const RefPtr<NG::FrameNode> & frameNode)128     bool IsScrollable(const RefPtr<NG::FrameNode>& frameNode)
129     {
130         CHECK_NULL_RETURN(frameNode, false);
131         auto tag = frameNode->GetTag();
132         return (tag == V2::LIST_ETS_TAG || tag == V2::SCROLL_ETS_TAG || tag == V2::TEXT_PICKER_ETS_TAG ||
133             tag == V2::WATERFLOW_ETS_TAG || tag == V2::SWIPER_ETS_TAG || tag == V2::GRID_ETS_TAG);
134     }
135 
GetScrollableAncestorClip(const RefPtr<NG::FrameNode> & frameNode)136     RectF GetScrollableAncestorClip(const RefPtr<NG::FrameNode>& frameNode)
137     {
138         RectF rect;
139         auto pipeline = frameNode->GetContextRefPtr();
140         CHECK_NULL_RETURN(pipeline, rect);
141         rect = pipeline->GetRootRect();
142         auto parentFrameNode = frameNode->GetAncestorNodeOfFrame(true);
143         while (parentFrameNode) {
144             if (!IsScrollable(parentFrameNode)) {
145                 parentFrameNode = parentFrameNode->GetAncestorNodeOfFrame(true);
146                 continue;
147             }
148             auto parentContent = parentFrameNode->GetTransformRectRelativeToWindow();
149             IntersectRectF(rect, parentContent);
150             parentFrameNode = parentFrameNode->GetAncestorNodeOfFrame(true);
151         }
152         return rect;
153     }
154 
ApplyFrameNodeTranformToRectWithoutRotate(const RectF & rect,const RefPtr<NG::FrameNode> & parent)155     RectF ApplyFrameNodeTranformToRectWithoutRotate(const RectF& rect, const RefPtr<NG::FrameNode>& parent) const
156     {
157         RectF newRect = rect;
158         if (!parent) {
159             return newRect;
160         }
161         auto parentRenderContext = parent->GetRenderContext();
162         if (!parentRenderContext) {
163             return newRect;
164         }
165         auto parentScale = parentRenderContext->GetTransformScale();
166         auto offset = rect.GetOffset();
167         if (parentScale) {
168             newRect.SetWidth(rect.Width() * parentScale.value().x);
169             newRect.SetHeight(rect.Height() * parentScale.value().y);
170             offset = OffsetF(offset.GetX() * parentScale.value().x, offset.GetY() * parentScale.value().y);
171         }
172         offset += parentRenderContext->GetPaintRectWithTransformWithoutDegree().GetOffset();
173         newRect.SetOffset(offset);
174         return newRect;
175     }
176 
GetTransformRectRelativeToWindowWithoutRotate(const RefPtr<NG::FrameNode> & frameNode)177     RectF GetTransformRectRelativeToWindowWithoutRotate(const RefPtr<NG::FrameNode>& frameNode) const
178     {
179         CHECK_NULL_RETURN(frameNode, RectF());
180         auto context = frameNode->GetRenderContext();
181         CHECK_NULL_RETURN(context, RectF());
182         RectF rect = context->GetPaintRectWithTransformWithoutDegree();
183         auto parent = frameNode->GetAncestorNodeOfFrame(true);
184         while (parent) {
185             rect = ApplyFrameNodeTranformToRectWithoutRotate(rect, parent);
186             parent = parent->GetAncestorNodeOfFrame(true);
187         }
188         return rect;
189     }
190 
ChangePaintNodeLayoutInner(const RefPtr<NG::FrameNode> & focusNode,const RefPtr<NG::FrameNode> & paintNode,int32_t left,int32_t top)191     void ChangePaintNodeLayoutInner(
192         const RefPtr<NG::FrameNode>& focusNode, const RefPtr<NG::FrameNode>& paintNode, int32_t left, int32_t top)
193     {
194         CHECK_NULL_VOID(focusNode);
195         auto trueCenter = GetPaintRectCenter(focusNode);
196         auto rect = GetTransformRectRelativeToWindowWithoutRotate(focusNode);
197         RectF showRect(trueCenter.GetX() - (rect.Width() / CENTER_DIVISOR) - left,
198             trueCenter.GetY() - (rect.Height() / CENTER_DIVISOR) - top,
199             rect.Width(), rect.Height());
200         auto scrollableAncestorsClip = GetScrollableAncestorClip(focusNode);
201         IntersectRectF(showRect, scrollableAncestorsClip);
202         auto host = GetHost();
203         CHECK_NULL_VOID(host);
204 
205         auto geometryNode = focusNode->GetGeometryNode();
206         CHECK_NULL_VOID(geometryNode);
207         auto focusNodeGeoNode = geometryNode->Clone();
208         focusNodeGeoNode->SetFrameOffset(NG::OffsetF(std::round(showRect.GetX()), std::round(showRect.GetY())));
209         focusNodeGeoNode->SetFrameHeight(std::round(showRect.Height()));
210         focusNodeGeoNode->SetFrameWidth(std::round(showRect.Width()));
211         host->SetGeometryNode(focusNodeGeoNode);
212         host->ForceSyncGeometryNode();
213 
214         auto paintRenderContext = host->GetRenderContext();
215         CHECK_NULL_VOID(paintRenderContext);
216         auto focusRenderContext = focusNode->GetRenderContext();
217         CHECK_NULL_VOID(focusRenderContext);
218         auto pipeline = focusNode->GetContextRefPtr();
219         CHECK_NULL_VOID(pipeline);
220         auto accessibilityManager = pipeline->GetAccessibilityManager();
221         CHECK_NULL_VOID(accessibilityManager);
222         auto degree = accessibilityManager->GetTransformDegreeRelativeToWindow(focusNode);
223         paintRenderContext->UpdateTransformRotate(NG::Vector5F(0, 0, 1, degree, 0));
224         if (focusRenderContext->HasOpacity()) {
225             paintRenderContext->UpdateOpacity(focusRenderContext->GetOpacityValue());
226         }
227     }
228 
OnDetachFromFocusNode()229     void OnDetachFromFocusNode()
230     {
231         RefPtr<NG::FrameNode> targetNode = focusNode_.Upgrade();
232         CHECK_NULL_VOID(targetNode);
233         focusNode_ = nullptr;
234     }
235 
GetFocusNode()236     WeakPtr<FrameNode>& GetFocusNode()
237     {
238         return focusNode_;
239     }
240 
GetRootNode()241     WeakPtr<UINode>& GetRootNode()
242     {
243         return rootNode_;
244     }
245 
246 private:
247     WeakPtr<FrameNode> focusNode_;
248     WeakPtr<UINode> rootNode_;
249 };
250 } // namespace OHOS::Ace::NG
251 #endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_PATTERNS_ROOT_ACCESSIBILITY_FOCUS_PAINT_NODE_PATTERN_H