1 /*
2  * Copyright (c) 2023-2024 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 "accessibility_property.h"
17 
18 #include "core/accessibility/accessibility_constants.h"
19 #include "core/components_ng/base/frame_node.h"
20 #include "core/pipeline_ng/pipeline_context.h"
21 
22 namespace OHOS::Ace::NG {
23 constexpr uint64_t ACTIONS = std::numeric_limits<uint64_t>::max();
GetSupportAction() const24 std::unordered_set<AceAction> AccessibilityProperty::GetSupportAction() const
25 {
26     static const AceAction allActions[] = {
27         AceAction::ACTION_NONE,
28         AceAction::GLOBAL_ACTION_BACK,
29         AceAction::CUSTOM_ACTION,
30         AceAction::ACTION_CLICK,
31         AceAction::ACTION_LONG_CLICK,
32         AceAction::ACTION_SCROLL_FORWARD,
33         AceAction::ACTION_SCROLL_BACKWARD,
34         AceAction::ACTION_FOCUS,
35         AceAction::ACTION_CLEAR_FOCUS,
36         AceAction::ACTION_ACCESSIBILITY_FOCUS,
37         AceAction::ACTION_CLEAR_ACCESSIBILITY_FOCUS,
38         AceAction::ACTION_NEXT_AT_MOVEMENT_GRANULARITY,
39         AceAction::ACTION_PREVIOUS_AT_MOVEMENT_GRANULARITY,
40         AceAction::ACTION_SET_TEXT,
41         AceAction::ACTION_COPY,
42         AceAction::ACTION_PASTE,
43         AceAction::ACTION_CUT,
44         AceAction::ACTION_SELECT,
45         AceAction::ACTION_SET_SELECTION,
46         AceAction::ACTION_CLEAR_SELECTION,
47         AceAction::ACTION_SET_CURSOR_POSITION,
48         AceAction::ACTION_EXEC_SUB_COMPONENT,
49     };
50 
51     std::unordered_set<AceAction> supportActions;
52     if (supportActions_ == 0) {
53         return supportActions;
54     }
55 
56     auto finalSupportActions = supportActions_ & ACTIONS;
57     for (auto action : allActions) {
58         if ((finalSupportActions & (1UL << static_cast<uint32_t>(action))) != 0) {
59             supportActions.emplace(action);
60         }
61     }
62     return supportActions;
63 }
64 
NotifyComponentChangeEvent(AccessibilityEventType eventType)65 void AccessibilityProperty::NotifyComponentChangeEvent(AccessibilityEventType eventType)
66 {
67     if (AceApplicationInfo::GetInstance().IsAccessibilityEnabled()) {
68         auto frameNode = host_.Upgrade();
69         CHECK_NULL_VOID(frameNode);
70         auto pipeline = frameNode->GetContext();
71         CHECK_NULL_VOID(pipeline);
72         pipeline->AddAccessibilityCallbackEvent(AccessibilityCallbackEventId::ON_SEND_ELEMENT_INFO_CHANGE,
73                                                 frameNode->GetAccessibilityId());
74     }
75 }
76 
GetText() const77 std::string AccessibilityProperty::GetText() const
78 {
79     return propText_.value_or("");
80 }
81 
GetGroupText(bool forceGetChildren) const82 std::string AccessibilityProperty::GetGroupText(bool forceGetChildren) const
83 {
84     std::string text;
85     GetGroupTextRecursive(forceGetChildren, text, false);
86     return text;
87 }
88 
GetGroupPreferAccessibilityText(bool forceGetChildren) const89 std::string AccessibilityProperty::GetGroupPreferAccessibilityText(bool forceGetChildren) const
90 {
91     std::string text;
92     GetGroupTextRecursive(forceGetChildren, text, true);
93     return text;
94 }
95 
GetGroupTextRecursive(bool forceGetChildren,std::string & text,bool preferAccessibilityText) const96 void AccessibilityProperty::GetGroupTextRecursive(bool forceGetChildren, std::string& text,
97                                                   bool preferAccessibilityText) const
98 {
99     auto node = host_.Upgrade();
100     CHECK_NULL_VOID(node);
101     if (node->IsInternal()) {
102         return;
103     }
104     auto level = GetAccessibilityLevel();
105     if (level == Level::AUTO || level == Level::YES_STR) {
106         std::string accessibilityText = GetAccessibilityText();
107         auto nodeText = preferAccessibilityText && !accessibilityText.empty() ? accessibilityText : GetText();
108         if (!text.empty() && !nodeText.empty()) {
109             text += ", ";
110         }
111         text += nodeText;
112     } else if (level == Level::NO_HIDE_DESCENDANTS) {
113         return;
114     }
115     // Do not change text if level is no
116 
117     if (!(forceGetChildren || IsAccessibilityGroup())) {
118         return;
119     }
120     auto& children = node->GetFrameChildren();
121     for (auto& childWeak : children) {
122         auto child = childWeak.Upgrade();
123         if (child == nullptr) {
124             continue;
125         }
126         child->GetAccessibilityProperty<AccessibilityProperty>()->GetGroupTextRecursive(true, text,
127                                                                                         preferAccessibilityText);
128     }
129 }
130 
GetScrollOffSet() const131 float AccessibilityProperty::GetScrollOffSet() const
132 {
133     return DEFAULT_ACCESSIBILITY_SCROLL_OFFSET;
134 }
135 
HoverTest(const PointF & point,const RefPtr<FrameNode> & root,std::unique_ptr<HoverTestDebugTraceInfo> & debugInfo)136 AccessibilityHoverTestPath AccessibilityProperty::HoverTest(
137     const PointF& point,
138     const RefPtr<FrameNode>& root,
139     std::unique_ptr<HoverTestDebugTraceInfo>& debugInfo)
140 {
141     AccessibilityHoverTestPath path;
142     CHECK_NULL_RETURN(root, path);
143     ACE_SCOPED_TRACE("AccessibilityHoverTest");
144     bool ancestorGroupFlag = false;
145     auto accessibilityProperty = root->GetAccessibilityProperty<NG::AccessibilityProperty>();
146     if (accessibilityProperty != nullptr) {
147         ancestorGroupFlag = accessibilityProperty->IsAccessibilityGroup();
148     }
149     AccessibilityProperty::HoverTestRecursive(point, root, path, debugInfo, ancestorGroupFlag);
150     return path;
151 }
152 
GetHitTestModeStr(HitTestMode hitTestMode,std::string & testModeStr)153 void GetHitTestModeStr(HitTestMode hitTestMode, std::string& testModeStr)
154 {
155     switch (hitTestMode) {
156         case HitTestMode::HTMDEFAULT:
157             testModeStr = "Default";
158             break;
159         case HitTestMode::HTMBLOCK:
160             testModeStr = "Block";
161             break;
162         case HitTestMode::HTMTRANSPARENT:
163             testModeStr = "Transparent";
164             break;
165         case HitTestMode::HTMNONE:
166             testModeStr = "None";
167             break;
168         default:
169             testModeStr = "Unsupported";
170     }
171 }
172 
CreateNodeSearchInfo(const RefPtr<FrameNode> & node,const PointF & parentPoint,bool & ancestorGroupFlag)173 std::unique_ptr<JsonValue> AccessibilityProperty::CreateNodeSearchInfo(const RefPtr<FrameNode>& node,
174     const PointF& parentPoint, bool& ancestorGroupFlag)
175 {
176     auto nodeInfo = JsonUtil::Create();
177     nodeInfo->Put("id", node->GetAccessibilityId());
178     nodeInfo->Put("tag", node->GetTag().c_str());
179     if (!node->IsRootNode()) {
180         if (node->GetParent()) {
181             nodeInfo->Put("parent", node->GetParent()->GetAccessibilityId());
182         } else {
183             nodeInfo->Put("parent", -1);
184         }
185     }
186     nodeInfo->Put("visible", node->IsVisible());
187     auto [shouldSearchSelf, shouldSearchChildren, groupFlag]
188         = AccessibilityProperty::GetSearchStrategy(node, ancestorGroupFlag);
189     nodeInfo->Put("shouldSearchSelf", shouldSearchSelf);
190     nodeInfo->Put("shouldSearchChildren", shouldSearchChildren);
191     nodeInfo->Put("currentGroup", groupFlag);
192 
193     auto renderContext = node->GetRenderContext();
194     auto rect = renderContext->GetPaintRectWithoutTransform();
195     PointF selfPoint = parentPoint;
196     renderContext->GetPointWithRevert(selfPoint);
197     bool hitSelf = rect.IsInnerRegion(selfPoint);
198     nodeInfo->Put("hitNode", hitSelf);
199     nodeInfo->Put("rect", rect.ToString().c_str());
200     nodeInfo->Put("hoverPoint", selfPoint.ToString().c_str());
201     nodeInfo->Put("clip", renderContext->GetClipEdge().value_or(false));
202 
203     auto eventHub = node->GetEventHub<EventHub>();
204     nodeInfo->Put("enabled", eventHub->IsEnabled());
205 
206     auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
207     if (accessibilityProperty != nullptr) {
208         nodeInfo->Put("accessibilityLevel", accessibilityProperty->GetAccessibilityLevel().c_str());
209         nodeInfo->Put("accessibilityGroup", accessibilityProperty->IsAccessibilityGroup());
210         nodeInfo->Put("hasVirtualNode", accessibilityProperty->HasAccessibilityVirtualNode());
211         nodeInfo->Put("accessibilityText", accessibilityProperty->GetAccessibilityText().c_str());
212         nodeInfo->Put("accessibilityDescription", accessibilityProperty->GetAccessibilityDescription().c_str());
213     }
214 
215     std::string testModeStr = "";
216     GetHitTestModeStr(node->GetHitTestMode(), testModeStr);
217     nodeInfo->Put("hitTestMode", testModeStr.c_str());
218     return nodeInfo;
219 }
220 
ProcessHoverTestRecursive(const PointF & noOffsetPoint,const RefPtr<FrameNode> & node,AccessibilityHoverTestPath & path,std::unique_ptr<HoverTestDebugTraceInfo> & debugInfo,RecursiveParam recursiveParam)221 bool AccessibilityProperty::ProcessHoverTestRecursive(const PointF& noOffsetPoint, const RefPtr<FrameNode>& node,
222     AccessibilityHoverTestPath& path, std::unique_ptr<HoverTestDebugTraceInfo>& debugInfo,
223     RecursiveParam recursiveParam)
224 {
225     auto property = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
226     auto virtualNode = property->GetAccessibilityVirtualNode();
227     if (virtualNode != nullptr) {
228         auto frameNode = AceType::DynamicCast<FrameNode>(virtualNode);
229         CHECK_NULL_RETURN(frameNode, false);
230 
231         if (AccessibilityProperty::HoverTestRecursive(noOffsetPoint, frameNode, path, debugInfo,
232             recursiveParam.ancestorGroupFlag)) {
233             return true;
234         }
235     } else {
236         auto children = node->GetFrameChildren();
237         for (auto childWeak = children.rbegin(); childWeak != children.rend(); ++childWeak) {
238             auto child = childWeak->Upgrade();
239             if (child == nullptr) {
240                 continue;
241             }
242             if (AccessibilityProperty::HoverTestRecursive(noOffsetPoint, child, path, debugInfo,
243                 recursiveParam.ancestorGroupFlag)) {
244                 return true;
245             }
246         }
247     }
248     return recursiveParam.hitTarget;
249 }
250 
HoverTestRecursive(const PointF & parentPoint,const RefPtr<FrameNode> & node,AccessibilityHoverTestPath & path,std::unique_ptr<HoverTestDebugTraceInfo> & debugInfo,bool & ancestorGroupFlag)251 bool AccessibilityProperty::HoverTestRecursive(
252     const PointF& parentPoint,
253     const RefPtr<FrameNode>& node,
254     AccessibilityHoverTestPath& path,
255     std::unique_ptr<HoverTestDebugTraceInfo>& debugInfo,
256     bool& ancestorGroupFlag)
257 {
258     if (!node->IsAccessibilityVirtualNode()) {
259         if (!node->IsActive() || node->IsInternal()) {
260             return false;
261         }
262     }
263     if (debugInfo != nullptr) {
264         auto nodeInfo = CreateNodeSearchInfo(node, parentPoint, ancestorGroupFlag);
265         debugInfo->trace.push_back(std::move(nodeInfo));
266     }
267     bool hitTarget = false;
268     if (!node->IsVisible()) {
269         return false;
270     }
271 
272     auto [shouldSearchSelf, shouldSearchChildren, currentGroupFlag]
273         = AccessibilityProperty::GetSearchStrategy(node, ancestorGroupFlag);
274 
275     auto renderContext = node->GetRenderContext();
276     auto rect = renderContext->GetPaintRectWithoutTransform();
277     PointF selfPoint = parentPoint;
278     renderContext->GetPointWithRevert(selfPoint);
279     bool hitSelf = rect.IsInnerRegion(selfPoint);
280     if (hitSelf && shouldSearchSelf
281         && (IsAccessibilityFocusable(node) || IsTagInModalDialog(node) || HitAccessibilityHoverPriority(node))) {
282         hitTarget = true;
283         path.push_back(node);
284     }
285     bool hasClip = renderContext->GetClipEdge().value_or(false);
286     if (hasClip && !hitSelf) {
287         return false;
288     }
289 
290     if (shouldSearchChildren) {
291         PointF noOffsetPoint = selfPoint - rect.GetOffset();
292         RecursiveParam recursiveParam;
293         recursiveParam.hitTarget = hitTarget;
294         recursiveParam.ancestorGroupFlag = currentGroupFlag;
295         return ProcessHoverTestRecursive(noOffsetPoint, node, path, debugInfo, recursiveParam);
296     }
297     return hitTarget;
298 }
299 
UpdateSearchStrategyByHitTestMode(HitTestMode hitTestMode,bool & shouldSearchSelf,bool & shouldSearchChildren)300 void UpdateSearchStrategyByHitTestMode(HitTestMode hitTestMode, bool& shouldSearchSelf, bool& shouldSearchChildren)
301 {
302     switch (hitTestMode) {
303         case HitTestMode::HTMBLOCK:
304             shouldSearchChildren = false;
305             break;
306         case HitTestMode::HTMTRANSPARENT:
307             break;
308         case HitTestMode::HTMNONE:
309             shouldSearchSelf = false;
310             break;
311         default:
312             break;
313     }
314 }
315 
316 static const std::set<std::string> TAGS_CROSS_PROCESS_COMPONENT = {
317     V2::XCOMPONENT_ETS_TAG,
318     V2::UI_EXTENSION_COMPONENT_ETS_TAG,
319     V2::EMBEDDED_COMPONENT_ETS_TAG,
320     V2::FORM_ETS_TAG,
321     V2::ISOLATED_COMPONENT_ETS_TAG,
322     V2::WEB_ETS_TAG,
323 };
324 
325 static const std::set<std::string> TAGS_MODAL_DIALOG_COMPONENT = {
326     V2::MENU_WRAPPER_ETS_TAG,
327     V2::SELECT_ETS_TAG,
328     V2::DIALOG_ETS_TAG,
329     V2::SHEET_PAGE_TAG,
330     V2::SHEET_WRAPPER_TAG,
331 };
332 
IsTagInCrossProcessComponent(const std::string & tag)333 bool AccessibilityProperty::IsTagInCrossProcessComponent(const std::string& tag)
334 {
335     if (TAGS_CROSS_PROCESS_COMPONENT.find(tag) != TAGS_CROSS_PROCESS_COMPONENT.end()) {
336         return true;
337     }
338     return false;
339 }
340 
IsTagInModalDialog(const RefPtr<FrameNode> & node)341 bool AccessibilityProperty::IsTagInModalDialog(const RefPtr<FrameNode>& node)
342 {
343     CHECK_NULL_RETURN(node, false);
344     return TAGS_MODAL_DIALOG_COMPONENT.find(node->GetTag()) != TAGS_MODAL_DIALOG_COMPONENT.end();
345 }
346 
HitAccessibilityHoverPriority(const RefPtr<FrameNode> & node)347 bool AccessibilityProperty::HitAccessibilityHoverPriority(const RefPtr<FrameNode>& node)
348 {
349     CHECK_NULL_RETURN(node, false);
350     auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
351     CHECK_NULL_RETURN(accessibilityProperty, false);
352     return accessibilityProperty->IsAccessibilityHoverPriority();
353 }
354 
GetSearchStrategy(const RefPtr<FrameNode> & node,bool & ancestorGroupFlag)355 std::tuple<bool, bool, bool> AccessibilityProperty::GetSearchStrategy(const RefPtr<FrameNode>& node,
356     bool& ancestorGroupFlag)
357 {
358     bool shouldSearchSelf = true;
359     bool shouldSearchChildren = true;
360     bool currentGroupFlag = false;
361     auto level = AccessibilityProperty::Level::AUTO;
362     do {
363         auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
364         if (accessibilityProperty != nullptr) {
365             level = accessibilityProperty->GetAccessibilityLevel();
366             currentGroupFlag = accessibilityProperty->IsAccessibilityGroup();
367             bool hasAccessibilityText = accessibilityProperty->HasAccessibilityTextOrDescription();
368             if (level == AccessibilityProperty::Level::YES_STR) {
369                 break;
370             } else if (level == AccessibilityProperty::Level::NO_HIDE_DESCENDANTS) {
371                 shouldSearchSelf = false;
372                 shouldSearchChildren = false;
373                 break;
374             } else {
375                 if (level == AccessibilityProperty::Level::NO_STR) {
376                     shouldSearchSelf = false;
377                 } else {
378                     // shouldSearchSelf is true here
379                     if (hasAccessibilityText) {
380                         break;
381                     }
382                 }
383             }
384         }
385         auto eventHub = node->GetEventHub<EventHub>();
386         if (!eventHub->IsEnabled()) {
387             shouldSearchChildren = false;
388             // Fall through to update `shouldSearchSelf`
389         }
390         HitTestMode hitTestMode = node->GetHitTestMode();
391         UpdateSearchStrategyByHitTestMode(hitTestMode, shouldSearchSelf, shouldSearchChildren);
392         if (accessibilityProperty != nullptr && accessibilityProperty->HasAccessibilityVirtualNode() &&
393             accessibilityProperty->GetAccessibilityLevel() != AccessibilityProperty::Level::NO_HIDE_DESCENDANTS) {
394             shouldSearchChildren = true;
395         }
396     } while (0);
397     shouldSearchSelf = IsTagInCrossProcessComponent(node->GetTag()) ? true : shouldSearchSelf;
398     if (ancestorGroupFlag == true) {
399         if (level != AccessibilityProperty::Level::YES_STR) {
400             shouldSearchSelf = false;
401         }
402         currentGroupFlag = true;
403     }
404 
405     return std::make_tuple(shouldSearchSelf, shouldSearchChildren, currentGroupFlag);
406 }
407 
408 static const std::set<std::string> TAGS_FOCUSABLE = {
409     V2::CHECKBOX_ETS_TAG,
410     V2::CHECKBOXGROUP_ETS_TAG,
411     V2::GAUGE_ETS_TAG,
412     V2::MARQUEE_ETS_TAG,
413     V2::MENU_ETS_TAG,
414     V2::MENU_ITEM_ETS_TAG,
415     V2::MENU_ITEM_GROUP_ETS_TAG,
416     V2::NAVIGATION_VIEW_ETS_TAG,
417     V2::DATE_PICKER_ETS_TAG,
418     V2::PROGRESS_ETS_TAG,
419     V2::RADIO_ETS_TAG,
420     V2::RATING_ETS_TAG,
421     V2::SCROLL_BAR_ETS_TAG,
422     V2::SELECT_ETS_TAG,
423     V2::SLIDER_ETS_TAG,
424     V2::STEPPER_ETS_TAG,
425     V2::TEXT_ETS_TAG,
426     V2::TEXTCLOCK_ETS_TAG,
427     V2::TEXT_PICKER_ETS_TAG,
428     V2::TEXTTIMER_ETS_TAG,
429     V2::TIME_PICKER_ETS_TAG,
430     V2::TOGGLE_ETS_TAG,
431     V2::WEB_ETS_TAG,
432     V2::XCOMPONENT_ETS_TAG,
433     V2::UI_EXTENSION_COMPONENT_ETS_TAG,
434     V2::EMBEDDED_COMPONENT_ETS_TAG,
435     V2::FORM_ETS_TAG
436 };
437 
IsAccessibilityFocusableTag(const std::string & tag)438 bool AccessibilityProperty::IsAccessibilityFocusableTag(const std::string &tag)
439 {
440     if (TAGS_FOCUSABLE.find(tag) != TAGS_FOCUSABLE.end()) {
441         return true;
442     }
443     return false;
444 }
445 
IsAccessibilityFocusableDebug(const RefPtr<FrameNode> & node,std::unique_ptr<JsonValue> & info)446 bool AccessibilityProperty::IsAccessibilityFocusableDebug(const RefPtr<FrameNode>& node,
447     std::unique_ptr<JsonValue>& info)
448 {
449     bool focusable = IsAccessibilityFocusable(node);
450     info->Put("id", node->GetAccessibilityId());
451     info->Put("tag", node->GetTag().c_str());
452     if (!node->IsRootNode()) {
453         info->Put("parent", node->GetParent()->GetAccessibilityId());
454     }
455     info->Put("selected", focusable);
456 
457     auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
458     if (accessibilityProperty != nullptr) {
459         info->Put("accessibilityLevel", accessibilityProperty->GetAccessibilityLevel().c_str());
460         info->Put("accessibilityGroup", accessibilityProperty->IsAccessibilityGroup());
461         info->Put("hasVirtualNode", accessibilityProperty->HasAccessibilityVirtualNode());
462         info->Put("accessibilityText", accessibilityProperty->GetAccessibilityText().c_str());
463         info->Put("accessibilityDescription", accessibilityProperty->GetAccessibilityDescription().c_str());
464         info->Put("text", accessibilityProperty->GetText().c_str());
465         info->Put("hasAction", accessibilityProperty->HasAction());
466     }
467 
468     auto eventHub = node->GetEventHub<EventHub>();
469     info->Put("enabled", eventHub->IsEnabled());
470     auto gestureEventHub = eventHub->GetGestureEventHub();
471     if (gestureEventHub != nullptr) {
472         info->Put("clickable", gestureEventHub->IsAccessibilityClickable());
473         info->Put("longClickable", gestureEventHub->IsAccessibilityLongClickable());
474     }
475     return focusable;
476 }
477 
478 
IsAccessibilityFocusable(const RefPtr<FrameNode> & node)479 bool AccessibilityProperty::IsAccessibilityFocusable(const RefPtr<FrameNode>& node)
480 {
481     if (node->IsRootNode()) {
482         return false;
483     }
484     bool focusable = false;
485     do {
486         auto accessibilityProperty = node->GetAccessibilityProperty<NG::AccessibilityProperty>();
487         if (accessibilityProperty != nullptr) {
488             auto level = accessibilityProperty->GetAccessibilityLevel();
489             if (level == AccessibilityProperty::Level::YES_STR) {
490                 focusable = true;
491                 break;
492             }
493             if (level == AccessibilityProperty::Level::NO_STR) {
494                 break;
495             }
496             if (accessibilityProperty->IsAccessibilityGroup() ||
497                 accessibilityProperty->HasAccessibilityVirtualNode() ||
498                 accessibilityProperty->HasAction() ||
499                 accessibilityProperty->HasAccessibilityTextOrDescription() ||
500                 !accessibilityProperty->GetText().empty()) {
501                 focusable = true;
502                 break;
503             }
504         }
505 
506         auto eventHub = node->GetEventHub<EventHub>();
507         if (!eventHub->IsEnabled()) {
508             focusable = true;
509             break;
510         }
511         auto gestureEventHub = eventHub->GetGestureEventHub();
512         if (gestureEventHub != nullptr) {
513             if (gestureEventHub->IsAccessibilityClickable() ||
514                 gestureEventHub->IsAccessibilityLongClickable()) {
515                 focusable = true;
516                 break;
517             }
518         }
519 
520         if (TAGS_FOCUSABLE.find(node->GetTag()) != TAGS_FOCUSABLE.end()) {
521             focusable = true;
522             break;
523         }
524     } while (0);
525     if (IsTagInCrossProcessComponent(node->GetTag())) {
526         focusable = true;
527     }
528     return focusable;
529 }
530 
HasAccessibilityTextOrDescription() const531 bool AccessibilityProperty::HasAccessibilityTextOrDescription() const
532 {
533     return !accessibilityText_.value_or("").empty() ||
534         !accessibilityDescription_.value_or("").empty();
535 }
536 
HasAction() const537 bool AccessibilityProperty::HasAction() const
538 {
539     return (supportActions_ & ACTIONS) != 0 ||
540         IsCheckable() ||
541         IsScrollable() ||
542         IsEditable() ||
543         IsDeletable();
544 }
545 
SetAccessibilityActions(uint32_t actions)546 void AccessibilityProperty::SetAccessibilityActions(uint32_t actions)
547 {
548     accessibilityActions_ = actions;
549 }
550 
ResetAccessibilityActions()551 void AccessibilityProperty::ResetAccessibilityActions()
552 {
553     accessibilityActions_ = std::nullopt;
554 }
555 
HasAccessibilityActions()556 bool AccessibilityProperty::HasAccessibilityActions()
557 {
558     return accessibilityActions_.has_value();
559 }
560 
GetAccessibilityActions() const561 uint32_t AccessibilityProperty::GetAccessibilityActions() const
562 {
563     return accessibilityActions_.value_or(0);
564 }
565 
SetAccessibilityRole(const std::string & role)566 void AccessibilityProperty::SetAccessibilityRole(const std::string& role)
567 {
568     accessibilityRole_ = role;
569 }
570 
ResetAccessibilityRole()571 void AccessibilityProperty::ResetAccessibilityRole()
572 {
573     accessibilityRole_ = std::nullopt;
574 }
575 
HasAccessibilityRole()576 bool AccessibilityProperty::HasAccessibilityRole()
577 {
578     return accessibilityRole_.has_value();
579 }
580 
GetAccessibilityRole() const581 std::string AccessibilityProperty::GetAccessibilityRole() const
582 {
583     return accessibilityRole_.value_or("");
584 }
585 
SetActions(const ActionsImpl & actionsImpl)586 void AccessibilityProperty::SetActions(const ActionsImpl& actionsImpl)
587 {
588     actionsImpl_ = actionsImpl;
589 }
590 
ActionsDefined(uint32_t action)591 bool AccessibilityProperty::ActionsDefined(uint32_t action)
592 {
593     if (!HasAccessibilityActions()) {
594         return false;
595     }
596     if (!actionsImpl_) {
597         return false;
598     }
599     int result = GetAccessibilityActions() & action;
600     return result != 0;
601 }
602 
SetUserDisabled(const bool & isDisabled)603 void AccessibilityProperty::SetUserDisabled(const bool& isDisabled)
604 {
605     isDisabled_ = isDisabled;
606 }
607 
HasUserDisabled()608 bool AccessibilityProperty::HasUserDisabled()
609 {
610     return isDisabled_.has_value();
611 }
612 
IsUserDisabled()613 bool AccessibilityProperty::IsUserDisabled()
614 {
615     return isDisabled_.value_or(false);
616 }
617 
SetUserSelected(const bool & isSelected)618 void AccessibilityProperty::SetUserSelected(const bool& isSelected)
619 {
620     isSelected_ = isSelected;
621 }
622 
HasUserSelected()623 bool AccessibilityProperty::HasUserSelected()
624 {
625     return isSelected_.has_value();
626 }
627 
IsUserSelected()628 bool AccessibilityProperty::IsUserSelected()
629 {
630     return isSelected_.value_or(false);
631 }
632 
ResetUserSelected()633 void AccessibilityProperty::ResetUserSelected()
634 {
635     isSelected_.reset();
636 }
637 
SetUserCheckedType(const int32_t & checkedType)638 void AccessibilityProperty::SetUserCheckedType(const int32_t& checkedType)
639 {
640     checkedType_ = checkedType;
641 }
642 
HasUserCheckedType()643 bool AccessibilityProperty::HasUserCheckedType()
644 {
645     return checkedType_.has_value();
646 }
647 
GetUserCheckedType()648 int32_t AccessibilityProperty::GetUserCheckedType()
649 {
650     return checkedType_.value_or(0);
651 }
652 
ResetUserCheckedType()653 void AccessibilityProperty::ResetUserCheckedType()
654 {
655     checkedType_.reset();
656 }
657 
SetUserCheckable(const bool & checkable)658 void AccessibilityProperty::SetUserCheckable(const bool& checkable)
659 {
660     isUserCheckable_ = checkable;
661 }
662 
HasUserCheckable()663 bool AccessibilityProperty::HasUserCheckable()
664 {
665     return isUserCheckable_.has_value();
666 }
667 
IsUserCheckable()668 bool AccessibilityProperty::IsUserCheckable()
669 {
670     return isUserCheckable_.value_or(false);
671 }
672 
ResetUserCheckable()673 void AccessibilityProperty::ResetUserCheckable()
674 {
675     isUserCheckable_.reset();
676 }
677 
SetUserMinValue(const int32_t & minValue)678 void AccessibilityProperty::SetUserMinValue(const int32_t& minValue)
679 {
680     minValue_ = minValue;
681 }
682 
HasUserMinValue()683 bool AccessibilityProperty::HasUserMinValue()
684 {
685     return minValue_.has_value();
686 }
687 
GetUserMinValue()688 int32_t AccessibilityProperty::GetUserMinValue()
689 {
690     return minValue_.value_or(-1);
691 }
692 
SetUserMaxValue(const int32_t & maxValue)693 void AccessibilityProperty::SetUserMaxValue(const int32_t& maxValue)
694 {
695     maxValue_ = maxValue;
696 }
697 
HasUserMaxValue()698 bool AccessibilityProperty::HasUserMaxValue()
699 {
700     return maxValue_.has_value();
701 }
702 
GetUserMaxValue()703 int32_t AccessibilityProperty::GetUserMaxValue()
704 {
705     return maxValue_.value_or(-1);
706 }
707 
SetUserCurrentValue(const int32_t & currentValue)708 void AccessibilityProperty::SetUserCurrentValue(const int32_t& currentValue)
709 {
710     currentValue_ = currentValue;
711 }
712 
HasUserCurrentValue()713 bool AccessibilityProperty::HasUserCurrentValue()
714 {
715     return currentValue_.has_value();
716 }
717 
GetUserCurrentValue()718 int32_t AccessibilityProperty::GetUserCurrentValue()
719 {
720     return currentValue_.value_or(-1);
721 }
722 
SetUserTextValue(const std::string & textValue)723 void AccessibilityProperty::SetUserTextValue(const std::string& textValue)
724 {
725     textValue_ = textValue;
726 }
727 
HasUserTextValue()728 bool AccessibilityProperty::HasUserTextValue()
729 {
730     return textValue_.has_value();
731 }
732 
GetUserTextValue()733 std::string AccessibilityProperty::GetUserTextValue()
734 {
735     return textValue_.value_or("");
736 }
737 
SetAccessibilityGroup(bool accessibilityGroup)738 void AccessibilityProperty::SetAccessibilityGroup(bool accessibilityGroup)
739 {
740     if (accessibilityGroup == accessibilityGroup_) {
741         return;
742     }
743     accessibilityGroup_ = accessibilityGroup;
744     NotifyComponentChangeEvent(AccessibilityEventType::ELEMENT_INFO_CHANGE);
745 }
746 
SetAccessibilityTextPreferred(bool accessibilityTextPreferred)747 void AccessibilityProperty::SetAccessibilityTextPreferred(bool accessibilityTextPreferred)
748 {
749     accessibilityTextPreferred_ = accessibilityTextPreferred;
750 }
751 
SetAccessibilityText(const std::string & text)752 void AccessibilityProperty::SetAccessibilityText(const std::string& text)
753 {
754     if (text == accessibilityText_.value_or("")) {
755         return;
756     }
757     accessibilityText_ = text;
758     NotifyComponentChangeEvent(AccessibilityEventType::TEXT_CHANGE);
759 }
760 
SetAccessibilityTextWithEvent(const std::string & text)761 void AccessibilityProperty::SetAccessibilityTextWithEvent(const std::string& text)
762 {
763     if (text == accessibilityText_.value_or("")) {
764         return;
765     }
766     accessibilityText_ = text;
767     NotifyComponentChangeEvent(AccessibilityEventType::TEXT_CHANGE);
768 }
769 
SetAccessibilityDescription(const std::string & accessibilityDescription)770 void AccessibilityProperty::SetAccessibilityDescription(const std::string& accessibilityDescription)
771 {
772     if (accessibilityDescription == accessibilityDescription_.value_or("")) {
773         return;
774     }
775     accessibilityDescription_ = accessibilityDescription;
776     NotifyComponentChangeEvent(AccessibilityEventType::TEXT_CHANGE);
777 }
778 
SetAccessibilityDescriptionWithEvent(const std::string & accessibilityDescription)779 void AccessibilityProperty::SetAccessibilityDescriptionWithEvent(const std::string& accessibilityDescription)
780 {
781     if (accessibilityDescription == accessibilityDescription_.value_or("")) {
782         return;
783     }
784     accessibilityDescription_ = accessibilityDescription;
785     NotifyComponentChangeEvent(AccessibilityEventType::TEXT_CHANGE);
786 }
787 
IsAccessibilityTextPreferred() const788 bool AccessibilityProperty::IsAccessibilityTextPreferred() const
789 {
790     return accessibilityTextPreferred_;
791 }
792 
SetAccessibilityLevel(const std::string & accessibilityLevel)793 void AccessibilityProperty::SetAccessibilityLevel(const std::string& accessibilityLevel)
794 {
795     auto backupLevel = accessibilityLevel_.value_or("");
796 
797     if (accessibilityLevel == Level::YES_STR ||
798         accessibilityLevel == Level::NO_STR ||
799         accessibilityLevel == Level::NO_HIDE_DESCENDANTS) {
800         accessibilityLevel_ = accessibilityLevel;
801     } else {
802         accessibilityLevel_ = Level::AUTO;
803     }
804 
805     if (backupLevel != accessibilityLevel_.value_or("")) {
806         NotifyComponentChangeEvent(AccessibilityEventType::ELEMENT_INFO_CHANGE);
807     }
808 }
809 
IsAccessibilityHoverPriority() const810 bool AccessibilityProperty::IsAccessibilityHoverPriority() const
811 {
812     return accessibilityHoverPriority_;
813 }
814 
SetAccessibilityHoverPriority(bool hoverPriority)815 void AccessibilityProperty::SetAccessibilityHoverPriority(bool hoverPriority)
816 {
817     // true means node consume barrierfree hover event prior to brothers
818     accessibilityHoverPriority_ = hoverPriority;
819 }
820 
821 } // namespace OHOS::Ace::NG
822