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