1 /*
2  * Copyright (c) 2021-2023 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/components_ng/event/focus_hub.h"
17 
18 #include <cinttypes>
19 #include <cstdint>
20 
21 #include "base/geometry/ng/offset_t.h"
22 #include "base/geometry/ng/rect_t.h"
23 #include "base/log/dump_log.h"
24 #include "base/utils/utils.h"
25 #include "core/common/ace_application_info.h"
26 #include "core/components/theme/app_theme.h"
27 #include "core/components_ng/base/frame_node.h"
28 #include "core/components_ng/base/geometry_node.h"
29 #include "core/components_ng/event/gesture_event_hub.h"
30 #include "core/components_ng/pattern/scrollable/scrollable_pattern.h"
31 #include "core/components_ng/pattern/scrollable/scrollable_utils.h"
32 #include "core/components_v2/inspector/inspector_constants.h"
33 #include "core/event/ace_event_handler.h"
34 #include "core/pipeline_ng/pipeline_context.h"
35 #ifdef WINDOW_SCENE_SUPPORTED
36 #include "core/components_ng/pattern/window_scene/helper/window_scene_helper.h"
37 #endif
38 
39 #ifndef ACE_UNITTEST
40 #ifdef ENABLE_STANDARD_INPUT
41 #include "core/components_ng/pattern/text_field/on_text_changed_listener_impl.h"
42 #endif
43 #endif
44 
45 namespace OHOS::Ace::NG {
46 constexpr uint32_t DELAY_TIME_FOR_RESET_UEC = 50;
47 namespace {
48 template <bool isReverse>
AnyOfUINode(const RefPtr<UINode> & node,const std::function<bool (const RefPtr<FocusHub> &)> & operation)49 bool AnyOfUINode(const RefPtr<UINode>& node, const std::function<bool(const RefPtr<FocusHub>&)>& operation)
50 {
51     const auto& children = node->GetChildren(true);
52     using IterType = std::conditional_t<isReverse, decltype(children.crbegin()), decltype(children.cbegin())>;
53     IterType begin, end;
54     if constexpr (isReverse) {
55         begin = children.crbegin();
56         end = children.crend();
57     } else {
58         begin = children.cbegin();
59         end = children.cend();
60     }
61     for (auto iter = begin; iter != end; ++iter) {
62         const auto& uiChild = *iter;
63         if (!uiChild || !uiChild->IsOnMainTree()) {
64             continue;
65         }
66         auto frameChild = AceType::DynamicCast<FrameNode>(uiChild);
67         if (frameChild && frameChild->GetFocusType() != FocusType::DISABLE) {
68             const auto focusHub = frameChild->GetFocusHub();
69             if (focusHub && operation(focusHub)) {
70                 return true;
71             }
72         } else if (AnyOfUINode<isReverse>(uiChild, operation)) {
73             return true;
74         }
75     }
76     return false;
77 }
78 }
79 
GetFocusManager() const80 RefPtr<FocusManager> FocusHub::GetFocusManager() const
81 {
82     auto frameNode = GetFrameNode();
83     CHECK_NULL_RETURN(frameNode, nullptr);
84     auto context = frameNode->GetContextRefPtr();
85     CHECK_NULL_RETURN(context, nullptr);
86     auto focusManager = context->GetOrCreateFocusManager();
87     return focusManager;
88 }
89 
GetFrameNode() const90 RefPtr<FrameNode> FocusHub::GetFrameNode() const
91 {
92     auto eventHub = eventHub_.Upgrade();
93     return eventHub ? eventHub->GetFrameNode() : nullptr;
94 }
95 
GetGeometryNode() const96 RefPtr<GeometryNode> FocusHub::GetGeometryNode() const
97 {
98     auto frameNode = GetFrameNode();
99     return frameNode ? frameNode->GetGeometryNode() : nullptr;
100 }
101 
GetInspectorKey() const102 std::optional<std::string> FocusHub::GetInspectorKey() const
103 {
104     auto frameNode = GetFrameNode();
105     CHECK_NULL_RETURN(frameNode, std::nullopt);
106     return frameNode->GetInspectorId();
107 }
108 
GetParentFocusHub() const109 RefPtr<FocusHub> FocusHub::GetParentFocusHub() const
110 {
111     auto frameNode = GetFrameNode();
112     CHECK_NULL_RETURN(frameNode, nullptr);
113     auto parentNode = frameNode->GetFocusParent();
114     return parentNode ? parentNode->GetFocusHub() : nullptr;
115 }
116 
GetRootFocusHub()117 RefPtr<FocusHub> FocusHub::GetRootFocusHub()
118 {
119     RefPtr<FocusHub> parent = AceType::Claim(this);
120     while (parent->GetParentFocusHub()) {
121         parent = parent->GetParentFocusHub();
122     }
123     return parent;
124 }
125 
GetFocusLeaf()126 RefPtr<FocusHub> FocusHub::GetFocusLeaf()
127 {
128     auto leafFocusNode = AceType::Claim(this);
129     auto nextFocusNode = leafFocusNode;
130     while (nextFocusNode && nextFocusNode->IsFocusable()) {
131         if (nextFocusNode->focusDepend_ == FocusDependence::SELF) {
132             return nextFocusNode;
133         }
134         leafFocusNode = nextFocusNode;
135         nextFocusNode = nextFocusNode->GetLastWeakFocusNode().Upgrade();
136     }
137     return leafFocusNode;
138 }
139 
GetFrameName() const140 std::string FocusHub::GetFrameName() const
141 {
142     auto frameNode = GetFrameNode();
143     return frameNode ? frameNode->GetTag() : "NULL";
144 }
145 
GetFrameId() const146 int32_t FocusHub::GetFrameId() const
147 {
148     auto frameNode = GetFrameNode();
149     return frameNode ? frameNode->GetId() : -1;
150 }
151 
152 template <bool isReverse>
AnyChildFocusHub(const std::function<bool (const RefPtr<FocusHub> &)> & operation)153 bool FocusHub::AnyChildFocusHub(const std::function<bool(const RefPtr<FocusHub>&)>& operation)
154 {
155     RefPtr<UINode> node = GetFrameNode();
156     CHECK_NULL_RETURN(node, false);
157     return AnyOfUINode<isReverse>(node, operation);
158 }
159 
AnyChildFocusHub(bool isReverse,const std::function<bool (const RefPtr<FocusHub> &)> & operation)160 bool FocusHub::AnyChildFocusHub(bool isReverse, const std::function<bool(const RefPtr<FocusHub>&)>& operation)
161 {
162     return isReverse ? AnyChildFocusHub<true>(operation) : AnyChildFocusHub<false>(operation);
163 }
164 
165 template <bool isReverse>
AllChildFocusHub(const std::function<void (const RefPtr<FocusHub> &)> & operation)166 void FocusHub::AllChildFocusHub(const std::function<void(const RefPtr<FocusHub>&)>& operation)
167 {
168     AnyChildFocusHub<isReverse>([&operation](const RefPtr<FocusHub>& focusHub) {
169         operation(focusHub);
170         return false;
171     });
172 }
173 template void FocusHub::AllChildFocusHub<true>(const std::function<void(const RefPtr<FocusHub>&)>&);
174 template void FocusHub::AllChildFocusHub<false>(const std::function<void(const RefPtr<FocusHub>&)>&);
175 
SkipFocusMoveBeforeRemove() const176 bool FocusHub::SkipFocusMoveBeforeRemove() const
177 {
178     return ((GetFrameName() == V2::MENU_WRAPPER_ETS_TAG) ||
179         (GetFrameName() == V2::SHEET_WRAPPER_TAG));
180 }
181 
FlushChildrenFocusHub(std::list<RefPtr<FocusHub>> & focusNodes)182 std::list<RefPtr<FocusHub>>::iterator FocusHub::FlushChildrenFocusHub(std::list<RefPtr<FocusHub>>& focusNodes)
183 {
184     focusNodes.clear();
185     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
186     decltype(focusNodes.begin()) lastIter;
187     bool hasLastFocus = false;
188     AllChildFocusHub([&focusNodes, &lastIter, &hasLastFocus, lastFocusNode](const RefPtr<FocusHub>& child) {
189         auto iter = focusNodes.emplace(focusNodes.end(), child);
190         if (child && lastFocusNode == child) {
191             lastIter = iter;
192             hasLastFocus = true;
193         }
194         return false;
195     });
196     return hasLastFocus ? lastIter : focusNodes.end();
197 }
198 
HandleKeyEvent(const KeyEvent & keyEvent)199 bool FocusHub::HandleKeyEvent(const KeyEvent& keyEvent)
200 {
201     if (!IsCurrentFocus()) {
202         return false;
203     }
204     bool shiftTabPressed = keyEvent.IsShiftWith(KeyCode::KEY_TAB);
205     bool leftArrowPressed = keyEvent.code == KeyCode::KEY_DPAD_LEFT;
206     hasBackwardMovement_ = keyEvent.action == KeyAction::DOWN && (shiftTabPressed || leftArrowPressed);
207 
208     bool tabOnlyPressed = (keyEvent.code == KeyCode::KEY_TAB) && (!shiftTabPressed);
209     bool rightArrowPressed = keyEvent.code == KeyCode::KEY_DPAD_RIGHT;
210     hasForwardMovement_ = keyEvent.action == KeyAction::DOWN && (tabOnlyPressed || rightArrowPressed);
211 
212     return OnKeyEvent(keyEvent);
213 }
214 
DumpFocusTree(int32_t depth)215 void FocusHub::DumpFocusTree(int32_t depth)
216 {
217     if (focusType_ == FocusType::NODE) {
218         DumpFocusNodeTree(depth);
219     } else if (focusType_ == FocusType::SCOPE) {
220         DumpFocusScopeTree(depth);
221     }
222 }
223 
DumpFocusNodeTree(int32_t depth)224 void FocusHub::DumpFocusNodeTree(int32_t depth)
225 {
226     if (DumpLog::GetInstance().GetDumpFile()) {
227         std::string information = GetFrameName();
228         if (IsCurrentFocus()) {
229             information += "(Node*)";
230         } else {
231             information += "(Node)";
232         }
233         information += (" id:" + std::to_string(GetFrameId()));
234         information += (GetInspectorKey().has_value() ? " idstr:" + GetInspectorKey().value() : "");
235         if (IsTabStop()) {
236             information += " TabStop:true";
237         }
238         if (!IsFocusable()) {
239             information = "(-)" + information;
240             information += IsEnabled() ? "" : " Enabled:false";
241             information += IsShow() ? "" : " Show:false";
242             information += focusable_ ? "" : " Focusable:false";
243             information += parentFocusable_ ? "" : " ParentFocusable:false";
244         }
245         information += IsDefaultFocus() ? "[Default]" : "";
246         if (!focusScopeId_.empty() && (focusPriority_ == FocusPriority::PRIOR)) {
247             information += (" prior-focus-in-" + focusScopeId_);
248         }
249         if (!focusScopeId_.empty() && (focusPriority_ == FocusPriority::PREVIOUS)) {
250             information += (" previous-focus-in-" + focusScopeId_);
251         }
252         auto focusMgr = GetFocusManager();
253         if (focusMgr && focusMgr->GetLastFocusStateNode() == this) {
254             information += " [Painted]";
255         }
256         DumpFocusUie();
257         DumpLog::GetInstance().Print(depth, information, 0);
258     }
259 }
260 
DumpFocusScopeTree(int32_t depth)261 void FocusHub::DumpFocusScopeTree(int32_t depth)
262 {
263     std::list<RefPtr<FocusHub>> focusNodes;
264     FlushChildrenFocusHub(focusNodes);
265     if (DumpLog::GetInstance().GetDumpFile()) {
266         std::string information = GetFrameName();
267         if (IsCurrentFocus()) {
268             information += "(Scope*)";
269         } else {
270             information += "(Scope)";
271         }
272         information += (" id:" + std::to_string(GetFrameId()));
273         information += (GetInspectorKey().has_value() ? " idstr:" + GetInspectorKey().value() : "");
274         if (IsTabStop()) {
275             information += " TabStop:true";
276         }
277         if (!IsFocusable()) {
278             information = "(-)" + information;
279             information += IsEnabled() ? "" : " Enabled:false";
280             information += IsShow() ? "" : " Show:false";
281             information += focusable_ ? "" : " Focusable:false";
282             information += parentFocusable_ ? "" : " ParentFocusable:false";
283         }
284         information += IsDefaultFocus() ? "[Default]" : "";
285         if (isFocusScope_ && !focusScopeId_.empty()) {
286             information += GetIsFocusGroup() ? " GroupId:" : " ScopeId:";
287             information += focusScopeId_;
288             information += arrowKeyStepOut_ ? "" : " ArrowKeyStepOut:false";
289         }
290         bool isPrior = (!focusScopeId_.empty() && (focusPriority_ == FocusPriority::PRIOR));
291         if (isPrior) {
292             information += (" prior-focus-in-" + focusScopeId_);
293         }
294         bool isPrevious = (!focusScopeId_.empty() && (focusPriority_ == FocusPriority::PREVIOUS));
295         if (isPrevious) {
296             information += (" previous-focus-in-" + focusScopeId_);
297         }
298         auto focusMgr = GetFocusManager();
299         if (focusMgr && focusMgr->GetLastFocusStateNode() == this) {
300             information += " [Painted]";
301         }
302         DumpLog::GetInstance().Print(depth, information, static_cast<int32_t>(focusNodes.size()));
303     }
304 
305     DumpFocusUie();
306     for (const auto& item : focusNodes) {
307         item->DumpFocusTree(depth + 1);
308     }
309 }
310 
DumpFocusUie()311 void FocusHub::DumpFocusUie()
312 {
313     auto frameNode = GetFrameNode();
314     CHECK_NULL_VOID(frameNode);
315     auto pattern = frameNode->GetPattern();
316     if (pattern && frameNode->GetTag() == V2::UI_EXTENSION_COMPONENT_TAG) {
317         pattern->DumpInfo();
318     }
319 }
320 
RequestFocusImmediately(bool isJudgeRootTree)321 bool FocusHub::RequestFocusImmediately(bool isJudgeRootTree)
322 {
323     TAG_LOGI(AceLogTag::ACE_FOCUS, "%{public}s/" SEC_PLD(%{public}d)
324         " RequestFocusImmediately",
325         GetFrameName().c_str(), SEC_PARAM(GetFrameId()));
326     return RequestFocusImmediatelyInner(isJudgeRootTree);
327 }
328 
RequestFocusImmediatelyInner(bool isJudgeRootTree)329 bool FocusHub::RequestFocusImmediatelyInner(bool isJudgeRootTree)
330 {
331     auto context = NG::PipelineContext::GetCurrentContextSafely();
332     CHECK_NULL_RETURN(context, false);
333     auto focusManager = context->GetOrCreateFocusManager();
334     CHECK_NULL_RETURN(focusManager, false);
335     if (context && context->GetIsFocusingByTab()) {
336         if (!IsFocusableByTab()) {
337             focusManager->TriggerRequestFocusCallback(RequestFocusResult::NON_FOCUSABLE_BY_TAB);
338             return false;
339         }
340     }
341 
342     if (IsCurrentFocus()) {
343         return true;
344     }
345 
346     if (!IsFocusableWholePath()) {
347         focusManager->TriggerRequestFocusCallback(RequestFocusResult::NON_FOCUSABLE_ANCESTOR);
348         return false;
349     }
350 
351     if (isJudgeRootTree && !IsOnRootTree()) {
352         focusManager->TriggerRequestFocusCallback(RequestFocusResult::NON_EXIST);
353         return false;
354     }
355 
356     currentFocus_ = true;
357 
358     if (onPreFocusCallback_) {
359         onPreFocusCallback_();
360     }
361     FocusManager::FocusGuard guard(focusManager->GetCurrentFocus(), SwitchingStartReason::REQUEST_FOCUS);
362     auto parent = GetParentFocusHub();
363     if (parent) {
364         if (focusManager) {
365             auto weakFocusViewList = focusManager->GetWeakFocusViewList();
366             for (const auto& weakFocusView : weakFocusViewList) {
367                 auto focusView = weakFocusView.Upgrade();
368                 auto viewRootScope = focusView ? focusView->GetViewRootScope() : nullptr;
369                 if (parent == viewRootScope) {
370                     focusView->SetIsViewRootScopeFocused(false);
371                     break;
372                 }
373             }
374         }
375         parent->SwitchFocus(AceType::Claim(this));
376     }
377 
378     focusManager->UpdateCurrentFocus(Claim(this), SwitchingUpdateReason::ON_FOCUS_NODE);
379     HandleFocus();
380     return true;
381 }
382 
IsViewRootScope()383 bool FocusHub::IsViewRootScope()
384 {
385     auto focusManager = GetFocusManager();
386     CHECK_NULL_RETURN(focusManager, false);
387     auto lastFocusView = focusManager->GetLastFocusView().Upgrade();
388     return (lastFocusView && lastFocusView->GetViewRootScope() == this);
389 }
390 
LostFocusToViewRoot()391 void FocusHub::LostFocusToViewRoot()
392 {
393     auto curFocusView = FocusView::GetCurrentFocusView();
394     CHECK_NULL_VOID(curFocusView);
395     auto viewRootScope = curFocusView->GetViewRootScope();
396     CHECK_NULL_VOID(viewRootScope);
397     TAG_LOGI(AceLogTag::ACE_FOCUS, "Lost focus to view root: %{public}s/%{public}d",
398         viewRootScope->GetFrameName().c_str(), viewRootScope->GetFrameId());
399     if (!viewRootScope->IsCurrentFocus()) {
400         TAG_LOGI(AceLogTag::ACE_FOCUS, "View root: %{public}s/%{public}d is not on focusing.",
401             viewRootScope->GetFrameName().c_str(), viewRootScope->GetFrameId());
402         return;
403     }
404     curFocusView->SetIsViewRootScopeFocused(true);
405     auto focusedChild = viewRootScope->lastWeakFocusNode_.Upgrade();
406     CHECK_NULL_VOID(focusedChild);
407     FocusManager::FocusGuard guard(viewRootScope, SwitchingStartReason::LOST_FOCUS_TO_VIEW_ROOT);
408     focusedChild->LostFocus(BlurReason::CLEAR_FOCUS);
409 }
410 
LostFocusToTabStop(const RefPtr<FocusHub> & focusNode)411 void FocusHub::LostFocusToTabStop(const RefPtr<FocusHub>& focusNode)
412 {
413     CHECK_NULL_VOID(focusNode);
414     if (!focusNode->IsCurrentFocus()) {
415         return;
416     }
417     auto focusedChild = focusNode->lastWeakFocusNode_.Upgrade();
418     CHECK_NULL_VOID(focusedChild);
419     FocusManager::FocusGuard guard(focusNode, SwitchingStartReason::LOST_FOCUS_TO_TABSTOP);
420     focusedChild->LostFocus(BlurReason::BACK_TO_TABSTOP);
421     focusNode->AllChildFocusHub([](const RefPtr<FocusHub>& child) {
422         if (child) {
423             child->ClearLastFocusNode();
424         }
425     });
426     focusNode->ClearLastFocusNode();
427 }
428 
LostFocus(BlurReason reason)429 void FocusHub::LostFocus(BlurReason reason)
430 {
431     TAG_LOGD(AceLogTag::ACE_FOCUS, "Node %{public}s/ " SEC_PLD(%{public}d)
432         " lost focus. Lost reason: %{public}d.",
433         GetFrameName().c_str(), SEC_PARAM(GetFrameId()), reason);
434     if (IsCurrentFocus()) {
435         blurReason_ = reason;
436         currentFocus_ = false;
437         OnBlur();
438     }
439 }
440 
LostSelfFocus()441 void FocusHub::LostSelfFocus()
442 {
443     if (IsCurrentFocus()) {
444         SetFocusable(false);
445         SetFocusable(true);
446     }
447 }
448 
RemoveSelf(BlurReason reason)449 void FocusHub::RemoveSelf(BlurReason reason)
450 {
451     if (SystemProperties::GetDebugEnabled()) {
452         TAG_LOGD(AceLogTag::ACE_FOCUS, "%{public}s/" SEC_PLD(%{public}d) " remove self focus.",
453             GetFrameName().c_str(), SEC_PARAM(GetFrameId()));
454     }
455     auto frameNode = GetFrameNode();
456     CHECK_NULL_VOID(frameNode);
457     auto focusView = frameNode->GetPattern<FocusView>();
458     auto* pipeline = frameNode->GetContext();
459     auto screenNode = pipeline ? pipeline->GetScreenNode() : nullptr;
460     auto screenFocusHub = screenNode ? screenNode->GetFocusHub() : nullptr;
461     auto parent = GetParentFocusHub();
462     if (parent && parent != screenFocusHub && !focusView) {
463         parent->RemoveChild(AceType::Claim(this), reason);
464     } else if (IsCurrentFocus()) {
465         FocusManager::FocusGuard guard(parent, SwitchingStartReason::REMOVE_SELF);
466         LostFocus(reason);
467     }
468     if (!focusScopeId_.empty()) {
469         RemoveFocusScopeIdAndPriority();
470     }
471 }
472 
RemoveChild(const RefPtr<FocusHub> & focusNode,BlurReason reason)473 void FocusHub::RemoveChild(const RefPtr<FocusHub>& focusNode, BlurReason reason)
474 {
475     // Not belong to this focus scope.
476     if (!focusNode || focusNode->GetParentFocusHub() != this) {
477         return;
478     }
479 
480     if (focusNode->IsCurrentFocus()) {
481         FocusManager::FocusGuard guard(Claim(this), SwitchingStartReason::REMOVE_CHILD);
482         // Try to goto next focus, otherwise goto previous focus.
483         if (!focusNode->SkipFocusMoveBeforeRemove() && !GoToNextFocusLinear(FocusStep::TAB) &&
484             !GoToNextFocusLinear(FocusStep::SHIFT_TAB)) {
485             lastWeakFocusNode_ = nullptr;
486             auto focusView = FocusView::GetCurrentFocusView();
487             auto mainViewRootScope = focusView ? focusView->GetViewRootScope() : nullptr;
488             if (mainViewRootScope && mainViewRootScope == AceType::Claim(this)) {
489 #ifndef IS_RELEASE_VERSION
490                 TAG_LOGI(AceLogTag::ACE_FOCUS,
491                     "Focus will stop at root scope %{public}s/%{public}d of focus view %{public}s/%{public}d",
492                     GetFrameName().c_str(), GetFrameId(), focusView->GetFrameName().c_str(), focusView->GetFrameId());
493 #endif
494                 focusView->SetIsViewRootScopeFocused(true);
495             } else {
496                 RemoveSelf(reason);
497             }
498         }
499         focusNode->LostFocus(reason);
500     }
501     if (lastWeakFocusNode_ == focusNode) {
502         lastWeakFocusNode_ = nullptr;
503     }
504 }
505 
506 // Need update RebuildChild function
507 
SetParentFocusable(bool parentFocusable)508 void FocusHub::SetParentFocusable(bool parentFocusable)
509 {
510     parentFocusable_ = parentFocusable;
511 }
512 
IsFocusable()513 bool FocusHub::IsFocusable()
514 {
515     if (focusType_ == FocusType::NODE) {
516         return IsFocusableNode();
517     }
518     if (focusType_ == FocusType::SCOPE) {
519         return IsFocusableScope();
520     }
521     return false;
522 }
523 
IsFocusableScope()524 bool FocusHub::IsFocusableScope()
525 {
526     if (!IsFocusableNode()) {
527         return false;
528     }
529     if (focusDepend_ == FocusDependence::SELF || focusDepend_ == FocusDependence::AUTO) {
530         return true;
531     }
532 
533     return AnyChildFocusHub([](const RefPtr<FocusHub>& focusHub) { return focusHub->IsFocusable(); });
534 }
535 
IsFocusableNode()536 bool FocusHub::IsFocusableNode()
537 {
538     return IsEnabled() && IsShow() && focusable_ && parentFocusable_;
539 }
540 
SetFocusable(bool focusable,bool isExplicit)541 void FocusHub::SetFocusable(bool focusable, bool isExplicit)
542 {
543     if (isExplicit) {
544         isFocusableExplicit_ = true;
545     } else if (isFocusableExplicit_) {
546         return;
547     } else {
548         implicitFocusable_ = focusable;
549     }
550     if (IsImplicitFocusableScope() && focusDepend_ == FocusDependence::CHILD) {
551         focusDepend_ = FocusDependence::AUTO;
552     }
553 
554     if (focusable_ == focusable) {
555         return;
556     }
557     focusable_ = focusable;
558     if (!focusable) {
559         if (SystemProperties::GetDebugEnabled()) {
560             TAG_LOGD(AceLogTag::ACE_FOCUS, "Set node %{public}s/ " SEC_PLD(%{public}d)
561                 " to be unfocusable", GetFrameName().c_str(), SEC_PARAM(GetFrameId()));
562         }
563         RemoveSelf(BlurReason::FOCUS_SWITCH);
564     }
565 }
566 
IsSyncRequestFocusable()567 bool FocusHub::IsSyncRequestFocusable()
568 {
569     if (focusType_ == FocusType::NODE) {
570         return IsSyncRequestFocusableNode();
571     }
572     if (focusType_ == FocusType::SCOPE) {
573         return IsSyncRequestFocusableScope();
574     }
575     return false;
576 }
577 
IsSyncRequestFocusableScope()578 bool FocusHub::IsSyncRequestFocusableScope()
579 {
580     if (!IsSyncRequestFocusableNode()) {
581         return false;
582     }
583     if (focusDepend_ == FocusDependence::SELF || focusDepend_ == FocusDependence::AUTO) {
584         return true;
585     }
586     return AnyChildFocusHub([](const RefPtr<FocusHub>& focusNode) { return focusNode->IsFocusable(); });
587 }
588 
IsSyncRequestFocusableNode()589 bool FocusHub::IsSyncRequestFocusableNode()
590 {
591     auto focusManager = GetFocusManager();
592     CHECK_NULL_RETURN(focusManager, false);
593     if (!IsEnabled() || !IsShow()) {
594         focusManager->TriggerRequestFocusCallback(RequestFocusResult::NON_EXIST);
595         return false;
596     }
597     if (!focusable_) {
598         focusManager->TriggerRequestFocusCallback(RequestFocusResult::NON_FOCUSABLE);
599         return false;
600     }
601     if (!parentFocusable_) {
602         focusManager->TriggerRequestFocusCallback(RequestFocusResult::NON_FOCUSABLE_ANCESTOR);
603         return false;
604     }
605     return true;
606 }
607 
IsEnabled() const608 bool FocusHub::IsEnabled() const
609 {
610     auto eventHub = eventHub_.Upgrade();
611     return eventHub ? eventHub->IsEnabled() : true;
612 }
613 
SetEnabled(bool enabled)614 void FocusHub::SetEnabled(bool enabled)
615 {
616     if (!enabled) {
617         if (SystemProperties::GetDebugEnabled()) {
618             TAG_LOGD(AceLogTag::ACE_FOCUS, "Set node %{public}s/" SEC_PLD(%{public}d)
619                 " to be disabled", GetFrameName().c_str(), SEC_PARAM(GetFrameId()));
620         }
621         RemoveSelf(BlurReason::FOCUS_SWITCH);
622     }
623 }
624 
IsShow() const625 bool FocusHub::IsShow() const
626 {
627     bool curIsVisible = true;
628     for (RefPtr<UINode> node = GetFrameNode(); curIsVisible && node; node = node->GetParent()) {
629         auto frameNode = AceType::DynamicCast<FrameNode>(node);
630         if (frameNode && !frameNode->IsVisible()) {
631             curIsVisible = false;
632         }
633     }
634     return curIsVisible;
635 }
636 
SetShow(bool show)637 void FocusHub::SetShow(bool show)
638 {
639     if (!show) {
640         if (SystemProperties::GetDebugEnabled()) {
641             TAG_LOGD(AceLogTag::ACE_FOCUS, "Set node %{public}s/" SEC_PLD(%{public}d)
642                 " to be unShown", GetFrameName().c_str(), SEC_PARAM(GetFrameId()));
643         }
644         RemoveSelf(BlurReason::FOCUS_SWITCH);
645     }
646 }
647 
IsCurrentFocusWholePath()648 bool FocusHub::IsCurrentFocusWholePath()
649 {
650     if (!currentFocus_) {
651         return false;
652     }
653     if (focusType_ == FocusType::NODE) {
654         return true;
655     }
656     if (focusType_ == FocusType::SCOPE) {
657         if (focusDepend_ == FocusDependence::SELF || focusDepend_ == FocusDependence::AUTO) {
658             return true;
659         }
660         std::list<RefPtr<FocusHub>> focusNodes;
661         auto itLastFocusNode = FlushChildrenFocusHub(focusNodes);
662         if (itLastFocusNode == focusNodes.end() || !(*itLastFocusNode)) {
663             return false;
664         }
665         return (*itLastFocusNode)->IsCurrentFocusWholePath();
666     }
667     return false;
668 }
669 
HasFocusedChild()670 bool FocusHub::HasFocusedChild()
671 {
672     if (!currentFocus_ || focusType_ != FocusType::SCOPE) {
673         return false;
674     }
675     return AnyChildFocusHub([](const RefPtr<FocusHub>& node) { return node && node->IsCurrentFocus(); });
676 }
677 
SetIsFocusOnTouch(bool isFocusOnTouch)678 void FocusHub::SetIsFocusOnTouch(bool isFocusOnTouch)
679 {
680     if (!focusCallbackEvents_) {
681         focusCallbackEvents_ = MakeRefPtr<FocusCallbackEvents>();
682     }
683     if (focusCallbackEvents_->isFocusOnTouch_.has_value() &&
684         focusCallbackEvents_->isFocusOnTouch_.value() == isFocusOnTouch) {
685         return;
686     }
687     focusCallbackEvents_->isFocusOnTouch_ = isFocusOnTouch;
688 
689     auto frameNode = GetFrameNode();
690     CHECK_NULL_VOID(frameNode);
691     auto gesture = frameNode->GetOrCreateGestureEventHub();
692     CHECK_NULL_VOID(gesture);
693 
694     if (!isFocusOnTouch && !focusOnTouchListener_) {
695         return;
696     }
697     if (!isFocusOnTouch && focusOnTouchListener_) {
698         gesture->RemoveTouchEvent(focusOnTouchListener_);
699         return;
700     }
701     if (!focusOnTouchListener_) {
702         auto touchCallback = [weak = WeakClaim(this)](const TouchEventInfo& info) {
703             auto focusHub = weak.Upgrade();
704             if (focusHub && info.GetTouches().front().GetTouchType() == TouchType::UP) {
705                 TAG_LOGI(AceLogTag::ACE_FOCUS, "node %{public}s/" SEC_PLD(%{public}d) " touch to be focused",
706                     focusHub->GetFrameName().c_str(), SEC_PARAM(focusHub->GetFrameId()));
707                 focusHub->RequestFocusImmediatelyInner();
708             }
709         };
710         focusOnTouchListener_ = MakeRefPtr<TouchEventImpl>(std::move(touchCallback));
711     }
712     gesture->AddTouchEvent(focusOnTouchListener_);
713 }
714 
OnKeyEvent(const KeyEvent & keyEvent)715 bool FocusHub::OnKeyEvent(const KeyEvent& keyEvent)
716 {
717     if (focusType_ == FocusType::SCOPE) {
718         return OnKeyEventScope(keyEvent);
719     }
720     if (focusType_ == FocusType::NODE) {
721         return OnKeyEventNode(keyEvent);
722     }
723     TAG_LOGW(AceLogTag::ACE_FOCUS, "Current node focus type: %{public}d is invalid.", focusType_);
724     return false;
725 }
726 
OnKeyPreIme(KeyEventInfo & info,const KeyEvent & keyEvent)727 bool FocusHub::OnKeyPreIme(KeyEventInfo& info, const KeyEvent& keyEvent)
728 {
729     auto onKeyPreIme = GetOnKeyPreIme();
730     if (onKeyPreIme) {
731         bool retPreIme = onKeyPreIme(info);
732         auto pipeline = PipelineContext::GetCurrentContext();
733         auto eventManager = pipeline->GetEventManager();
734         if (eventManager) {
735             eventManager->SetIsKeyConsumed(retPreIme);
736         }
737         return info.IsStopPropagation();
738     } else if (GetFrameName() == V2::UI_EXTENSION_COMPONENT_ETS_TAG) {
739         return ProcessOnKeyEventInternal(keyEvent);
740     } else {
741         return false;
742     }
743 }
744 
PrintOnKeyEventUserInfo(const KeyEvent & keyEvent,bool retCallback)745 void FocusHub::PrintOnKeyEventUserInfo(const KeyEvent& keyEvent, bool retCallback)
746 {
747     TAG_LOGI(AceLogTag::ACE_FOCUS,
748         "OnKeyEventUser: Node %{public}s/%{public}d handle KeyEvent(%{public}d, %{public}d) return: %{public}d",
749         GetFrameName().c_str(), GetFrameId(), keyEvent.code, keyEvent.action, retCallback);
750 }
751 
OnKeyEventNode(const KeyEvent & keyEvent)752 bool FocusHub::OnKeyEventNode(const KeyEvent& keyEvent)
753 {
754     ACE_DCHECK(IsCurrentFocus());
755     // ReDispatch keyEvent will NOT be consumed again.
756     if (keyEvent.isRedispatch) {
757         return false;
758     }
759 
760     auto node = GetFrameNode();
761     CHECK_NULL_RETURN(node, false);
762     auto* pipeline = node->GetContext();
763     CHECK_NULL_RETURN(pipeline, false);
764     auto info = KeyEventInfo(keyEvent);
765     if (pipeline->IsKeyInPressed(KeyCode::KEY_META_LEFT) ||
766         pipeline->IsKeyInPressed(KeyCode::KEY_META_RIGHT)) {
767         info.SetMetaKey(1);
768     }
769     if (keyEvent.isPreIme) {
770         return OnKeyPreIme(info, keyEvent);
771     }
772 
773     bool retInternal = OnKeyEventNodeInternal(keyEvent);
774     bool retCallback = OnKeyEventNodeUser(info, keyEvent);
775     if (!retInternal && !retCallback && keyEvent.action == KeyAction::DOWN) {
776         auto ret = false;
777         switch (keyEvent.code) {
778             case KeyCode::KEY_ESCAPE:
779                 ret = RequestNextFocusOfKeyEsc();
780                 break;
781             case KeyCode::KEY_ENTER:
782             case KeyCode::KEY_NUMPAD_ENTER:
783                 if (RequestNextFocusOfKeyEnter()) {
784                     ret = true;
785                     break;
786                 } else {
787                     [[fallthrough]];
788                 }
789             case KeyCode::KEY_SPACE:
790                 ret = OnClick(keyEvent);
791                 TAG_LOGI(AceLogTag::ACE_FOCUS,
792                     "OnClick: Node %{public}s/%{public}d handle KeyEvent(%{private}d, %{public}d) return: %{public}d",
793                     GetFrameName().c_str(), GetFrameId(), keyEvent.code, keyEvent.action, ret);
794                 break;
795             default:;
796         }
797         return ret;
798     }
799     return retInternal || retCallback;
800 }
801 
OnKeyEventNodeInternal(const KeyEvent & keyEvent)802 bool FocusHub::OnKeyEventNodeInternal(const KeyEvent& keyEvent)
803 {
804     auto node = GetFrameNode();
805     CHECK_NULL_RETURN(node, false);
806     auto* pipeline = node->GetContext();
807     CHECK_NULL_RETURN(pipeline, false);
808     bool isBypassInner = keyEvent.IsKey({ KeyCode::KEY_TAB }) && pipeline && pipeline->IsTabJustTriggerOnKeyEvent();
809     auto retInternal = false;
810     if ((GetFrameName() == V2::UI_EXTENSION_COMPONENT_ETS_TAG || GetFrameName() == V2::ISOLATED_COMPONENT_ETS_TAG)
811         && !IsCurrentFocus()) {
812         isBypassInner = false;
813     }
814     if (!isBypassInner && !onKeyEventsInternal_.empty()) {
815         retInternal = ProcessOnKeyEventInternal(keyEvent);
816         TAG_LOGI(AceLogTag::ACE_FOCUS,
817             "OnKeyEventInteral: Node %{public}s/%{public}d handle KeyEvent(%{private}d, %{public}d) "
818             "return: %{public}d",
819             GetFrameName().c_str(), GetFrameId(), keyEvent.code, keyEvent.action, retInternal);
820     }
821     return retInternal;
822 }
823 
OnKeyEventNodeUser(KeyEventInfo & info,const KeyEvent & keyEvent)824 bool FocusHub::OnKeyEventNodeUser(KeyEventInfo& info, const KeyEvent& keyEvent)
825 {
826     auto node = GetFrameNode();
827     CHECK_NULL_RETURN(node, false);
828     auto* pipeline = node->GetContext();
829     CHECK_NULL_RETURN(pipeline, false);
830     auto retCallback = false;
831     auto onKeyEventCallback = GetOnKeyCallback();
832     if (onKeyEventCallback) {
833         onKeyEventCallback(info);
834         retCallback = info.IsStopPropagation();
835         auto eventManager = pipeline->GetEventManager();
836         PrintOnKeyEventUserInfo(keyEvent, retCallback);
837     }
838 
839     auto onJSFrameNodeKeyCallback = GetOnJSFrameNodeKeyCallback();
840     if (onJSFrameNodeKeyCallback) {
841         onJSFrameNodeKeyCallback(info);
842         retCallback = info.IsStopPropagation();
843         PrintOnKeyEventUserInfo(keyEvent, retCallback);
844     }
845     return retCallback;
846 }
847 
OnKeyEventScope(const KeyEvent & keyEvent)848 bool FocusHub::OnKeyEventScope(const KeyEvent& keyEvent)
849 {
850     ACE_DCHECK(IsCurrentFocus());
851     std::list<RefPtr<FocusHub>> focusNodes;
852     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
853     if (lastFocusNode && lastFocusNode->HandleKeyEvent(keyEvent)) {
854         TAG_LOGD(AceLogTag::ACE_FOCUS,
855             "OnKeyEvent: Node %{public}s/%{public}d will not handle KeyEvent(code:%{private}d, action:%{public}d). "
856             "Because its child %{public}s/%{public}d already has consumed this event.",
857             GetFrameName().c_str(), GetFrameId(), keyEvent.code, keyEvent.action, lastFocusNode->GetFrameName().c_str(),
858             lastFocusNode->GetFrameId());
859         return true;
860     }
861 
862     if (OnKeyEventNode(keyEvent)) {
863         return true;
864     }
865 
866     if (keyEvent.isPreIme || keyEvent.action != KeyAction::DOWN) {
867         return false;
868     }
869 
870     auto node = GetFrameNode();
871     CHECK_NULL_RETURN(node, false);
872     auto* pipeline = node->GetContext();
873     CHECK_NULL_RETURN(pipeline, false);
874     if (!pipeline->GetIsFocusActive()) {
875         return false;
876     }
877     if (keyEvent.IsKey({ KeyCode::KEY_TAB }) && IsInFocusGroup()) {
878         return false;
879     }
880     if (keyEvent.IsKey({ KeyCode::KEY_TAB }) && pipeline->IsTabJustTriggerOnKeyEvent()) {
881         ScrollToLastFocusIndex();
882         return false;
883     }
884 
885     if (!CalculatePosition()) {
886         return false;
887     }
888 
889     return RequestNextFocusByKey(keyEvent);
890 }
891 
RequestNextFocusByKey(const KeyEvent & keyEvent)892 bool FocusHub::RequestNextFocusByKey(const KeyEvent& keyEvent)
893 {
894     switch (keyEvent.code) {
895         case KeyCode::TV_CONTROL_UP:
896             return RequestNextFocus(FocusStep::UP, GetRect());
897         case KeyCode::TV_CONTROL_DOWN:
898             return RequestNextFocus(FocusStep::DOWN, GetRect());
899         case KeyCode::TV_CONTROL_LEFT:
900             return RequestNextFocus(FocusStep::LEFT, GetRect());
901         case KeyCode::TV_CONTROL_RIGHT:
902             return RequestNextFocus(FocusStep::RIGHT, GetRect());
903         case KeyCode::KEY_TAB:
904             return RequestNextFocusOfKeyTab(keyEvent);
905         case KeyCode::KEY_MOVE_HOME:
906             return RequestNextFocus(FocusStep::LEFT_END, GetRect()) || RequestNextFocus(FocusStep::UP_END, GetRect());
907         case KeyCode::KEY_MOVE_END:
908             return RequestNextFocus(FocusStep::RIGHT_END, GetRect()) ||
909                    RequestNextFocus(FocusStep::DOWN_END, GetRect());
910         default:
911             return false;
912     }
913 }
914 
RequestNextFocusOfKeyTab(const KeyEvent & keyEvent)915 bool FocusHub::RequestNextFocusOfKeyTab(const KeyEvent& keyEvent)
916 {
917     auto frameNode = GetFrameNode();
918     CHECK_NULL_RETURN(frameNode, false);
919     auto* context = frameNode->GetContext();
920     CHECK_NULL_RETURN(context, false);
921     auto curFocusView = FocusView::GetCurrentFocusView();
922     auto entryFocusView = curFocusView ? curFocusView->GetEntryFocusView() : nullptr;
923     auto entryFocusViewHub = entryFocusView ? entryFocusView->GetFocusHub() : nullptr;
924     auto focusParent = GetParentFocusHub();
925     bool isCurrentHandledByFocusView =
926         (entryFocusViewHub && entryFocusViewHub == this) || !focusParent || !focusParent->IsCurrentFocus();
927     bool ret = false;
928     if (keyEvent.pressedCodes.size() == 1) {
929         context->SetIsFocusingByTab(true);
930         ret = RequestNextFocus(FocusStep::TAB, GetRect());
931         if (!ret && isCurrentHandledByFocusView) {
932             auto container = Container::GetContainer(context->GetInstanceId());
933             auto isDynamicRender = container == nullptr ? false : container->IsDynamicRender();
934             bool isFocusWindowIdSetted = context->IsFocusWindowIdSetted();
935             if (isFocusWindowIdSetted) {
936                 // Delay focus transfer to avoid focusbox twinkling when USC lost focus.
937                 // UEC should inherit common FocusHub to handle such case in the future.
938                 auto taskExecutor = context->GetTaskExecutor();
939                 CHECK_NULL_RETURN(taskExecutor, false);
940                 auto instanceId = context->GetInstanceId();
941                 taskExecutor->PostDelayedTask(
942                     [weak = WeakClaim(this), instanceId] {
943                         ContainerScope scope(instanceId);
944                         auto focusHub = weak.Upgrade();
945                         CHECK_NULL_VOID(focusHub);
946                         focusHub->FocusToHeadOrTailChild(true);
947                     }, TaskExecutor::TaskType::UI,
948                     DELAY_TIME_FOR_RESET_UEC, "FocusToHeadOrTailChildInUEC");
949                 return false;
950             } else if (isDynamicRender) {
951                 FocusToHeadOrTailChild(true);
952                 return false;
953             }
954             ret = FocusToHeadOrTailChild(true);
955         }
956         context->SetIsFocusingByTab(false);
957     } else if (keyEvent.IsShiftWith(KeyCode::KEY_TAB)) {
958         context->SetIsFocusingByTab(true);
959         ret = RequestNextFocus(FocusStep::SHIFT_TAB, GetRect());
960         if (!ret && isCurrentHandledByFocusView) {
961             auto container = Container::GetContainer(context->GetInstanceId());
962             auto isDynamicRender = container == nullptr ? false : container->IsDynamicRender();
963             if (context->IsFocusWindowIdSetted() || isDynamicRender) {
964                 FocusToHeadOrTailChild(false);
965                 return false;
966             }
967             ret = FocusToHeadOrTailChild(false);
968         }
969         context->SetIsFocusingByTab(false);
970     }
971     return ret;
972 }
973 
RequestNextFocusOfKeyEnter()974 bool FocusHub::RequestNextFocusOfKeyEnter()
975 {
976     if (IsTabStop() && focusType_ == FocusType::SCOPE) {
977         isSwitchByEnter_ = true;
978         OnFocusScope(true);
979         return true;
980     }
981     return false;
982 }
983 
RequestNextFocusOfKeyEsc()984 bool FocusHub::RequestNextFocusOfKeyEsc()
985 {
986     auto curFocusView = FocusView::GetCurrentFocusView();
987     CHECK_NULL_RETURN(curFocusView, false);
988     auto curFocusViewHub = curFocusView->GetFocusHub();
989     CHECK_NULL_RETURN(curFocusViewHub, false);
990     auto lastViewFocusHub = curFocusViewHub->GetFocusLeaf();
991     CHECK_NULL_RETURN(lastViewFocusHub, false);
992     auto viewRootScope = curFocusView->GetViewRootScope();
993     CHECK_NULL_RETURN(viewRootScope, false);
994     if (lastViewFocusHub != this || viewRootScope == this || curFocusViewHub == this) {
995         return false;
996     }
997     auto parent = GetParentFocusHub();
998     CHECK_NULL_RETURN(parent, false);
999     while (parent) {
1000         if (parent->IsTabStop()) {
1001             LostFocusToTabStop(parent);
1002             return true;
1003         }
1004         if (parent == viewRootScope) {
1005             break;
1006         }
1007         parent = parent->GetParentFocusHub();
1008     }
1009     return false;
1010 }
1011 
RequestFocus() const1012 void FocusHub::RequestFocus() const
1013 {
1014     if (IsCurrentFocus()) {
1015         return;
1016     }
1017     auto context = NG::PipelineContext::GetCurrentContextSafely();
1018     CHECK_NULL_VOID(context);
1019     TAG_LOGI(AceLogTag::ACE_FOCUS, "Node: %{public}s/" SEC_PLD(%{public}d) " RequestFocus.",
1020         GetFrameName().c_str(), SEC_PARAM(GetFrameId()));
1021     context->AddDirtyFocus(GetFrameNode());
1022 }
1023 
RequestNextFocus(FocusStep moveStep,const RectF & rect)1024 bool FocusHub::RequestNextFocus(FocusStep moveStep, const RectF& rect)
1025 {
1026     TAG_LOGI(AceLogTag::ACE_FOCUS, "Request next focus on node: %{public}s/" SEC_PLD(%{public}d)
1027         " by step: %{public}d.",
1028         GetFrameName().c_str(), SEC_PARAM(GetFrameId()), moveStep);
1029     SetScopeFocusAlgorithm();
1030     if (!focusAlgorithm_.getNextFocusNode) {
1031         if (focusAlgorithm_.scopeType == ScopeType::PROJECT_AREA) {
1032             auto lastFocusNode = lastWeakFocusNode_.Upgrade();
1033             CHECK_NULL_RETURN(lastFocusNode, false);
1034             RefPtr<FocusHub> nextFocusHub = nullptr;
1035             std::list<RefPtr<FocusHub>> children;
1036             FlushChildrenFocusHub(children);
1037             if (IsFocusStepTab(moveStep)) {
1038                 nextFocusHub = lastFocusNode->GetNearestNodeByProjectArea(
1039                     children, GetRealFocusStepByTab(moveStep, AceApplicationInfo::GetInstance().IsRightToLeft()));
1040             }
1041             if (!nextFocusHub) {
1042                 nextFocusHub = lastFocusNode->GetNearestNodeByProjectArea(children, moveStep);
1043             }
1044             if (!nextFocusHub || nextFocusHub == lastFocusNode) {
1045                 TAG_LOGI(
1046                     AceLogTag::ACE_FOCUS, "Request next focus failed becase cannot find next node by project area.");
1047                 return false;
1048             }
1049             auto ret = TryRequestFocus(nextFocusHub, rect, moveStep);
1050             TAG_LOGI(AceLogTag::ACE_FOCUS,
1051                 "Request next focus by project area. Next focus node is %{public}s/%{public}d. Return %{public}d",
1052                 nextFocusHub->GetFrameName().c_str(), nextFocusHub->GetFrameId(), ret);
1053             return ret;
1054         }
1055         if (focusAlgorithm_.direction != ScopeFocusDirection::UNIVERSAL && !IsFocusStepTab(moveStep) &&
1056             focusAlgorithm_.isVertical != IsFocusStepVertical(moveStep)) {
1057             TAG_LOGI(AceLogTag::ACE_FOCUS,
1058                 "Request next focus failed because direction of node(%{public}d) is different with step(%{public}d).",
1059                 focusAlgorithm_.isVertical, moveStep);
1060             return IsArrowKeyStepOut(moveStep);
1061         }
1062         auto ret = GoToNextFocusLinear(moveStep, rect);
1063         TAG_LOGI(AceLogTag::ACE_FOCUS, "Request next focus by default linear algorithm. Return %{public}d.", ret);
1064         return (ret || IsArrowKeyStepOut(moveStep));
1065     }
1066     if (!lastWeakFocusNode_.Upgrade()) {
1067         return IsArrowKeyStepOut(moveStep);
1068     }
1069     WeakPtr<FocusHub> nextFocusHubWeak;
1070     focusAlgorithm_.getNextFocusNode(moveStep, lastWeakFocusNode_, nextFocusHubWeak);
1071     auto nextFocusHub = nextFocusHubWeak.Upgrade();
1072     if (!nextFocusHub || nextFocusHub == lastWeakFocusNode_.Upgrade()) {
1073         TAG_LOGI(AceLogTag::ACE_FOCUS, "Request next focus failed by custom focus algorithm.");
1074         return IsArrowKeyStepOut(moveStep);
1075     }
1076     auto ret = TryRequestFocus(nextFocusHub, rect, moveStep);
1077     TAG_LOGI(AceLogTag::ACE_FOCUS,
1078         "Request next focus by custom focus algorithm. Next focus node is %{public}s/%{public}d. Return %{public}d",
1079         nextFocusHub->GetFrameName().c_str(), nextFocusHub->GetFrameId(), ret);
1080     return (ret || IsArrowKeyStepOut(moveStep));
1081 }
1082 
IsArrowKeyStepOut(FocusStep moveStep)1083 bool FocusHub::IsArrowKeyStepOut(FocusStep moveStep)
1084 {
1085     if (!IsFocusStepTab(moveStep) && GetIsFocusGroup() && !arrowKeyStepOut_) {
1086         TAG_LOGI(AceLogTag::ACE_FOCUS,
1087             "IsArrowKeyStepOut Node(%{public}s/%{public}d), step(%{public}d),"
1088             "this node is focus group and set can not step out!",
1089             GetFrameName().c_str(), GetFrameId(), moveStep);
1090         return true;
1091     }
1092     return false;
1093 }
1094 
FocusToHeadOrTailChild(bool isHead)1095 bool FocusHub::FocusToHeadOrTailChild(bool isHead)
1096 {
1097     if (!IsFocusableWholePath()) {
1098         return false;
1099     }
1100     if (GetIsFocusGroup() && !IsNestingFocusGroup()) {
1101         return RequestFocusImmediatelyInner();
1102     }
1103     if (focusType_ != FocusType::SCOPE || (focusType_ == FocusType::SCOPE && focusDepend_ == FocusDependence::SELF)) {
1104         return RequestFocusImmediatelyInner();
1105     }
1106 
1107     if (IsTabStop()) {
1108         std::list<RefPtr<FocusHub>> focusNodes;
1109         auto itLastFocusNode = FlushChildrenFocusHub(focusNodes);
1110         // A(Tabstop)->B(TabStop)->C
1111         //              `--------->D
1112         // if D is the last leaf node, then press the Tab key to shift the focus to C.
1113         if (!(IsCurrentFocus() && itLastFocusNode != focusNodes.end() && (*itLastFocusNode)->IsCurrentFocus())) {
1114             return RequestFocusImmediatelyInner();
1115         }
1116     }
1117     auto curFrameNode = GetFrameNode();
1118     auto curPattern = curFrameNode ? curFrameNode->GetPattern<ScrollablePattern>() : nullptr;
1119     auto scrollIndexAbility = curPattern ? curPattern->GetScrollIndexAbility() : nullptr;
1120     if (scrollIndexAbility) {
1121         scrollIndexAbility(isHead ? FocusHub::SCROLL_TO_HEAD : FocusHub::SCROLL_TO_TAIL);
1122         auto node = GetFrameNode();
1123         CHECK_NULL_RETURN(node, false);
1124         auto pipeline = node->GetContextRefPtr();
1125         if (pipeline) {
1126             pipeline->FlushUITasks();
1127         }
1128     }
1129 
1130     bool canChildBeFocused = false;
1131     canChildBeFocused = AnyChildFocusHub(
1132         !isHead, [isHead](const RefPtr<FocusHub>& node) { return node->FocusToHeadOrTailChild(isHead); });
1133     if (focusDepend_ == FocusDependence::CHILD) {
1134         return canChildBeFocused;
1135     }
1136     if (focusDepend_ == FocusDependence::AUTO) {
1137         if (!canChildBeFocused) {
1138             return RequestFocusImmediatelyInner();
1139         }
1140         return canChildBeFocused;
1141     }
1142     return false;
1143 }
1144 
OnClick(const KeyEvent & event)1145 bool FocusHub::OnClick(const KeyEvent& event)
1146 {
1147     auto onClickCallback = GetOnClickCallback();
1148     if (onClickCallback) {
1149         auto info = GestureEvent();
1150         info.SetTimeStamp(event.timeStamp);
1151         auto geometryNode = GetGeometryNode();
1152         CHECK_NULL_RETURN(geometryNode, false);
1153         auto rect = geometryNode->GetFrameRect();
1154         auto centerToWindow = Offset((rect.Left() + rect.Right()) / 2, (rect.Top() + rect.Bottom()) / 2);
1155         auto centerToNode = Offset((rect.Right() - rect.Left()) / 2, (rect.Bottom() - rect.Top()) / 2);
1156         info.SetGlobalLocation(centerToWindow);
1157         info.SetLocalLocation(centerToNode);
1158         info.SetSourceDevice(event.sourceType);
1159         info.SetDeviceId(event.deviceId);
1160         auto node = GetFrameNode();
1161         CHECK_NULL_RETURN(node, false);
1162         auto pipelineContext = node->GetContextRefPtr();
1163         if (pipelineContext) {
1164             auto windowOffset = pipelineContext->GetCurrentWindowRect().GetOffset() + centerToWindow;
1165             info.SetScreenLocation(windowOffset);
1166         }
1167         info.SetSourceTool(SourceTool::UNKNOWN);
1168         auto eventHub = eventHub_.Upgrade();
1169         if (eventHub) {
1170             auto targetImpl = eventHub->CreateGetEventTargetImpl();
1171             info.SetTarget(targetImpl().value_or(EventTarget()));
1172         }
1173         onClickCallback(info);
1174         return true;
1175     }
1176     return false;
1177 }
1178 
SwitchFocus(const RefPtr<FocusHub> & focusNode)1179 void FocusHub::SwitchFocus(const RefPtr<FocusHub>& focusNode)
1180 {
1181     if (focusType_ != FocusType::SCOPE) {
1182         TAG_LOGW(AceLogTag::ACE_FOCUS, "SwitchFocus: parent focus node is not a scope!");
1183         return;
1184     }
1185 
1186     auto focusNodeNeedBlur = lastWeakFocusNode_.Upgrade();
1187     lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(focusNode));
1188     TAG_LOGD(AceLogTag::ACE_FOCUS, "Switch focus from %{public}s/"
1189         SEC_PLD(%{public}d) " to %{public}s/" SEC_PLD(%{public}d),
1190         focusNodeNeedBlur ? focusNodeNeedBlur->GetFrameName().c_str() : "NULL",
1191         SEC_PARAM(focusNodeNeedBlur ? focusNodeNeedBlur->GetFrameId() : -1),
1192         focusNode->GetFrameName().c_str(),
1193         SEC_PARAM(focusNode->GetFrameId()));
1194     if (IsCurrentFocus()) {
1195         GetFocusManager()->UpdateCurrentFocus(Claim(this), SwitchingUpdateReason::SWITCH_FOCUS);
1196         if (focusNodeNeedBlur && focusNodeNeedBlur != focusNode) {
1197             focusNodeNeedBlur->LostFocus();
1198         }
1199     } else {
1200         RequestFocusImmediatelyInner();
1201     }
1202 }
1203 
GoToNextFocusLinear(FocusStep step,const RectF & rect)1204 bool FocusHub::GoToNextFocusLinear(FocusStep step, const RectF& rect)
1205 {
1206     if (step == FocusStep::NONE) {
1207         return false;
1208     }
1209     bool reverse = !IsFocusStepForward(step, AceApplicationInfo::GetInstance().IsRightToLeft());
1210     std::list<RefPtr<FocusHub>> focusNodes;
1211     auto itNewFocusNode = FlushChildrenFocusHub(focusNodes);
1212     if (focusNodes.empty()) {
1213         return false;
1214     }
1215     if (itNewFocusNode == focusNodes.end()) {
1216         itNewFocusNode = focusNodes.begin();
1217     }
1218     if (reverse) {
1219         if (itNewFocusNode == focusNodes.begin()) {
1220             itNewFocusNode = focusNodes.end();
1221             return false;
1222         }
1223         --itNewFocusNode;
1224 
1225         while (itNewFocusNode != focusNodes.begin()) {
1226             if (TryRequestFocus(*itNewFocusNode, rect, step)) {
1227                 return true;
1228             }
1229             --itNewFocusNode;
1230         }
1231         if (itNewFocusNode == focusNodes.begin()) {
1232             if (TryRequestFocus(*itNewFocusNode, rect, step)) {
1233                 return true;
1234             }
1235         }
1236     } else {
1237         if (itNewFocusNode != focusNodes.end()) {
1238             ++itNewFocusNode;
1239         }
1240         while (itNewFocusNode != focusNodes.end()) {
1241             if (TryRequestFocus(*itNewFocusNode, rect, step)) {
1242                 return true;
1243             }
1244             ++itNewFocusNode;
1245         }
1246     }
1247 
1248     return false;
1249 }
1250 
TryRequestFocus(const RefPtr<FocusHub> & focusNode,const RectF & rect,FocusStep step)1251 bool FocusHub::TryRequestFocus(const RefPtr<FocusHub>& focusNode, const RectF& rect, FocusStep step)
1252 {
1253     if (IsFocusStepTab(step) && focusNode->AcceptFocusOfPriorityChild()) {
1254         return focusNode->RequestFocusImmediatelyInner();
1255     }
1256     if (IsFocusStepTab(step) && focusNode->AcceptFocusOfSpecifyChild(step)) {
1257         return focusNode->RequestFocusImmediatelyInner();
1258     }
1259     if (!IsFocusStepTab(step) && step != FocusStep::NONE && focusNode->GetIsFocusGroup() &&
1260         !focusNode->IsNestingFocusGroup()) {
1261         return focusNode->RequestFocusImmediatelyInner();
1262     }
1263     if (rect.IsValid()) {
1264         RectF childRect;
1265         if (!CalculateRect(focusNode, childRect) ||
1266             !focusNode->AcceptFocusByRectOfLastFocus(rect - childRect.GetOffset())) {
1267             return false;
1268         }
1269     }
1270     return focusNode->RequestFocusImmediatelyInner();
1271 }
1272 
ClearLastFocusNode()1273 void FocusHub::ClearLastFocusNode()
1274 {
1275     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
1276     if (lastFocusNode) {
1277         lastFocusNode->ClearLastFocusNode();
1278         lastWeakFocusNode_ = nullptr;
1279     }
1280 }
1281 
CalculatePosition()1282 bool FocusHub::CalculatePosition()
1283 {
1284     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
1285     CHECK_NULL_RETURN(lastFocusNode, false);
1286     if (!lastFocusNode->IsCurrentFocus()) {
1287         return false;
1288     }
1289 
1290     RectF childRect;
1291     if (!CalculateRect(lastFocusNode, childRect)) {
1292         return false;
1293     }
1294 
1295     if (lastFocusNode->IsChild()) {
1296         auto lastFocusGeometryNode = lastFocusNode->GetGeometryNode();
1297         CHECK_NULL_RETURN(lastFocusGeometryNode, false);
1298         RectF rect(childRect.GetOffset(), lastFocusGeometryNode->GetFrameSize());
1299         lastFocusNode->SetRect(rect);
1300         SetRect(rect);
1301     } else {
1302         SetRect(lastFocusNode->GetRect() + childRect.GetOffset());
1303     }
1304 
1305     return true;
1306 }
1307 
SetScopeFocusAlgorithm()1308 void FocusHub::SetScopeFocusAlgorithm()
1309 {
1310     auto frame = GetFrameNode();
1311     CHECK_NULL_VOID(frame);
1312     auto pattern = frame->GetPattern();
1313     CHECK_NULL_VOID(pattern);
1314     focusAlgorithm_ = pattern->GetScopeFocusAlgorithm();
1315 }
1316 
SetLastFocusNodeIndex(const RefPtr<FocusHub> & focusNode)1317 void FocusHub::SetLastFocusNodeIndex(const RefPtr<FocusHub>& focusNode)
1318 {
1319     auto frame = GetFrameNode();
1320     CHECK_NULL_VOID(frame);
1321     auto pattern = frame->GetPattern();
1322     CHECK_NULL_VOID(pattern);
1323     lastFocusNodeIndex_ = pattern->GetFocusNodeIndex(focusNode);
1324 }
1325 
ScrollToLastFocusIndex() const1326 void FocusHub::ScrollToLastFocusIndex() const
1327 {
1328     if (lastFocusNodeIndex_ == -1) {
1329         return;
1330     }
1331     auto frame = GetFrameNode();
1332     CHECK_NULL_VOID(frame);
1333     auto pattern = frame->GetPattern();
1334     CHECK_NULL_VOID(pattern);
1335     pattern->ScrollToFocusNodeIndex(lastFocusNodeIndex_);
1336 }
1337 
OnFocus()1338 void FocusHub::OnFocus()
1339 {
1340     if (focusType_ == FocusType::NODE) {
1341         OnFocusNode();
1342     } else if (focusType_ == FocusType::SCOPE) {
1343         OnFocusScope();
1344     }
1345     // if root focused, it has no focus view to update.
1346     auto node = GetFrameNode();
1347     if (!node || node->IsRootNode()) {
1348         return;
1349     }
1350     UpdateFocusView();
1351 }
1352 
OnBlur()1353 void FocusHub::OnBlur()
1354 {
1355     if (focusType_ == FocusType::NODE) {
1356         OnBlurNode();
1357     } else if (focusType_ == FocusType::SCOPE) {
1358         OnBlurScope();
1359     }
1360 }
1361 
OnFocusNode()1362 void FocusHub::OnFocusNode()
1363 {
1364     TAG_LOGD(AceLogTag::ACE_FOCUS, "%{public}s/" SEC_PLD(%{public}d) " focus",
1365         GetFrameName().c_str(), SEC_PARAM(GetFrameId()));
1366     if (onFocusInternal_) {
1367         onFocusInternal_();
1368     }
1369     auto node = GetFrameNode();
1370     CHECK_NULL_VOID(node);
1371     auto pipeline = node->GetContextRefPtr();
1372     CHECK_NULL_VOID(pipeline);
1373     pipeline->AddAfterLayoutTask([weak = WeakClaim(this)]() {
1374         auto focusHub = weak.Upgrade();
1375         CHECK_NULL_VOID(focusHub);
1376         auto onFocusCallback = focusHub->GetOnFocusCallback();
1377         if (onFocusCallback) {
1378             onFocusCallback();
1379         }
1380         auto onJSFrameNodeFocusCallback = focusHub->GetOnJSFrameNodeFocusCallback();
1381         if (onJSFrameNodeFocusCallback) {
1382             onJSFrameNodeFocusCallback();
1383         }
1384     });
1385     auto parentFocusHub = GetParentFocusHub();
1386     if (parentFocusHub) {
1387         parentFocusHub->SetLastFocusNodeIndex(AceType::Claim(this));
1388     }
1389 
1390     auto focusManager = pipeline->GetOrCreateFocusManager();
1391     CHECK_NULL_VOID(focusManager);
1392 
1393     auto frameNode = GetFrameNode();
1394     CHECK_NULL_VOID(frameNode);
1395     frameNode->OnAccessibilityEvent(AccessibilityEventType::FOCUS);
1396 
1397     pipeline->RequestFrame();
1398 }
1399 
OnBlurNode()1400 void FocusHub::OnBlurNode()
1401 {
1402     TAG_LOGD(AceLogTag::ACE_FOCUS, "%{public}s/" SEC_PLD(%{public}d) " blur by %{public}d",
1403         GetFrameName().c_str(), SEC_PARAM(GetFrameId()), blurReason_);
1404     if (onBlurInternal_) {
1405         onBlurInternal_();
1406     }
1407     if (onBlurReasonInternal_) {
1408         onBlurReasonInternal_(blurReason_);
1409     }
1410     auto frameNode = GetFrameNode();
1411     CHECK_NULL_VOID(frameNode);
1412     auto* pipeline = frameNode->GetContext();
1413     CHECK_NULL_VOID(pipeline);
1414     pipeline->AddAfterLayoutTask([focusHub = Claim(this)]() {
1415         CHECK_NULL_VOID(focusHub);
1416         auto onBlurCallback = focusHub->GetOnBlurCallback();
1417         if (onBlurCallback) {
1418             onBlurCallback();
1419         }
1420         auto onJSFrameNodeBlurCallback_ = focusHub->GetOnJSFrameNodeBlurCallback();
1421         if (onJSFrameNodeBlurCallback_) {
1422             onJSFrameNodeBlurCallback_();
1423         }
1424     });
1425     if (blurReason_ != BlurReason::FRAME_DESTROY) {
1426         ClearFocusState();
1427     }
1428 
1429     pipeline->RequestFrame();
1430 }
1431 
CheckFocusStateStyle(bool onFocus)1432 void FocusHub::CheckFocusStateStyle(bool onFocus)
1433 {
1434     auto eventHub = eventHub_.Upgrade();
1435     CHECK_NULL_VOID(eventHub);
1436     if (onFocus) {
1437         eventHub->UpdateCurrentUIState(UI_STATE_FOCUSED);
1438     } else {
1439         eventHub->ResetCurrentUIState(UI_STATE_FOCUSED);
1440     }
1441 }
1442 
HasFocusStateStyle()1443 bool FocusHub::HasFocusStateStyle()
1444 {
1445     auto eventHub = eventHub_.Upgrade();
1446     CHECK_NULL_RETURN(eventHub, false);
1447     return eventHub->HasStateStyle(UI_STATE_FOCUSED);
1448 }
1449 
IsLeafFocusScope()1450 bool FocusHub::IsLeafFocusScope()
1451 {
1452     auto focusManager = GetFocusManager();
1453     CHECK_NULL_RETURN(focusManager, false);
1454     if (IsTabStop()) {
1455         if (isSwitchByEnter_) {
1456             if (focusDepend_ == FocusDependence::SELF) {
1457                 focusDepend_ = FocusDependence::AUTO;
1458             }
1459             isSwitchByEnter_ = false;
1460             return false;
1461         }
1462         focusManager->UpdateSwitchingEndReason(SwitchingEndReason::TAB_STOP);
1463         return true;
1464     }
1465     if (focusDepend_ == FocusDependence::SELF) {
1466         lastWeakFocusNode_ = nullptr;
1467         focusManager->UpdateSwitchingEndReason(SwitchingEndReason::DEPENDENCE_SELF);
1468         return true;
1469     }
1470     return false;
1471 }
1472 
OnFocusScope(bool currentHasFocused)1473 void FocusHub::OnFocusScope(bool currentHasFocused)
1474 {
1475     if (IsLeafFocusScope()) {
1476         if (!currentHasFocused) {
1477             OnFocusNode();
1478         }
1479         return;
1480     }
1481 
1482     std::list<RefPtr<FocusHub>> focusNodes;
1483     auto itLastFocusNode = FlushChildrenFocusHub(focusNodes);
1484     bool isAnyChildFocusable = focusNodes.empty()
1485                                    ? false
1486                                    : std::any_of(focusNodes.begin(), focusNodes.end(),
1487                                          [](const RefPtr<FocusHub>& focusNode) { return focusNode->IsFocusable(); });
1488 
1489     if (focusDepend_ == FocusDependence::AUTO && !isAnyChildFocusable) {
1490         lastWeakFocusNode_ = nullptr;
1491         OnFocusNode();
1492         auto focusManager = GetFocusManager();
1493         CHECK_NULL_VOID(focusManager);
1494         focusManager->UpdateSwitchingEndReason(SwitchingEndReason::NO_FOCUSABLE_CHILD);
1495         return;
1496     }
1497 
1498     if ((focusDepend_ == FocusDependence::AUTO || focusDepend_ == FocusDependence::CHILD) && isAnyChildFocusable) {
1499         auto itFocusNode = itLastFocusNode;
1500         if (RequestFocusByPriorityInScope()) {
1501             if (!currentHasFocused) {
1502                 OnFocusNode();
1503             }
1504             return;
1505         }
1506         do {
1507             if (itLastFocusNode == focusNodes.end()) {
1508                 itLastFocusNode = focusNodes.begin();
1509                 lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*itLastFocusNode));
1510                 if (itLastFocusNode == itFocusNode) {
1511                     break;
1512                 }
1513             }
1514             lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*itLastFocusNode));
1515             if ((*itLastFocusNode)->RequestFocusImmediatelyInner()) {
1516                 if (!currentHasFocused) {
1517                     OnFocusNode();
1518                 }
1519                 return;
1520             }
1521         } while ((++itLastFocusNode) != itFocusNode);
1522 
1523         // Not found any focusable node, clear focus.
1524         itLastFocusNode = focusNodes.end();
1525         lastWeakFocusNode_ = nullptr;
1526     }
1527 }
1528 
OnBlurScope()1529 void FocusHub::OnBlurScope()
1530 {
1531     OnBlurNode();
1532     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
1533     if (lastFocusNode) {
1534         lastFocusNode->LostFocus(blurReason_);
1535     }
1536 }
1537 
PaintFocusState(bool isNeedStateStyles)1538 bool FocusHub::PaintFocusState(bool isNeedStateStyles)
1539 {
1540     auto context = PipelineContext::GetCurrentContextSafely();
1541     CHECK_NULL_RETURN(context, false);
1542     auto frameNode = GetFrameNode();
1543     CHECK_NULL_RETURN(frameNode, false);
1544     auto renderContext = frameNode->GetRenderContext();
1545     CHECK_NULL_RETURN(renderContext, false);
1546     if (!context->GetIsFocusActive() || !IsNeedPaintFocusState()) {
1547         return false;
1548     }
1549 
1550     if (HasFocusStateStyle()) {
1551         if (isNeedStateStyles) {
1552             // do focus state style.
1553             CheckFocusStateStyle(true);
1554         }
1555         return true;
1556     }
1557 
1558     if (focusStyleType_ == FocusStyleType::NONE) {
1559         return false;
1560     }
1561 
1562     if (focusStyleType_ == FocusStyleType::FORCE_NONE) {
1563         return true;
1564     }
1565 
1566     if (focusStyleType_ == FocusStyleType::CUSTOM_REGION) {
1567         CHECK_NULL_RETURN(getInnerFocusRectFunc_, false);
1568         RoundRect focusRectInner;
1569         focusRectInner.SetRect({ -1, -1, -1, -1 });
1570         getInnerFocusRectFunc_(focusRectInner);
1571         if (!focusRectInner.GetRect().IsValid()) {
1572             return false;
1573         }
1574         return PaintInnerFocusState(focusRectInner);
1575     }
1576 
1577     auto appTheme = context->GetTheme<AppTheme>();
1578     CHECK_NULL_RETURN(appTheme, false);
1579     Color paintColor;
1580     if (box_.paintStyle_ && box_.paintStyle_->strokeColor) {
1581         paintColor = box_.paintStyle_->strokeColor.value();
1582     } else if (HasPaintColor()) {
1583         paintColor = GetPaintColor();
1584     } else {
1585         paintColor = appTheme->GetFocusColor();
1586     }
1587     Dimension paintWidth;
1588     if (box_.paintStyle_ && box_.paintStyle_->strokeWidth) {
1589         paintWidth = box_.paintStyle_->strokeWidth.value();
1590     } else if (HasPaintWidth()) {
1591         paintWidth = GetPaintWidth();
1592     } else {
1593         paintWidth = appTheme->GetFocusWidthVp();
1594     }
1595     if (NEAR_ZERO(paintWidth.Value())) {
1596         return true;
1597     }
1598 
1599     if (focusStyleType_ == FocusStyleType::CUSTOM_BORDER) {
1600         if (!HasPaintRect()) {
1601             return false;
1602         }
1603         renderContext->PaintFocusState(GetPaintRect(), paintColor, paintWidth);
1604         return true;
1605     }
1606 
1607     Dimension focusPaddingVp = Dimension(0.0, DimensionUnit::VP);
1608     if (box_.paintStyle_ && box_.paintStyle_->margin) {
1609         focusPaddingVp = box_.paintStyle_->margin.value();
1610     } else if (HasFocusPadding()) {
1611         focusPaddingVp = GetFocusPadding();
1612     } else if (focusStyleType_ == FocusStyleType::INNER_BORDER) {
1613         focusPaddingVp = -appTheme->GetFocusWidthVp();
1614     } else if (focusStyleType_ == FocusStyleType::OUTER_BORDER || focusStyleType_ == FocusStyleType::FORCE_BORDER) {
1615         focusPaddingVp = appTheme->GetFocusOutPaddingVp();
1616     }
1617     if (HasPaintRect()) {
1618         renderContext->PaintFocusState(GetPaintRect(), focusPaddingVp, paintColor, paintWidth);
1619     } else {
1620         renderContext->PaintFocusState(focusPaddingVp, paintColor, paintWidth);
1621     }
1622     return true;
1623 }
1624 
RaiseZIndex()1625 void FocusHub::RaiseZIndex()
1626 {
1627     auto frameNode = GetFrameNode();
1628     CHECK_NULL_VOID(frameNode);
1629     const auto& target = frameNode->GetRenderContext();
1630     if (target && !target->HasZIndex()) {
1631         target->UpdateZIndex(INT32_MAX); // default focus zIndex
1632         isRaisedZIndex_ = true;
1633     }
1634 }
1635 
PaintAllFocusState()1636 bool FocusHub::PaintAllFocusState()
1637 {
1638     auto focusManager = GetFocusManager();
1639     CHECK_NULL_RETURN(focusManager, false);
1640 
1641     if (PaintFocusState()) {
1642         focusManager->SetLastFocusStateNode(AceType::Claim(this));
1643         RaiseZIndex();
1644         if (onPaintFocusStateCallback_) {
1645             return onPaintFocusStateCallback_();
1646         }
1647         return !isFocusActiveWhenFocused_;
1648     }
1649     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
1650     if (lastFocusNode && lastFocusNode->IsCurrentFocus() && lastFocusNode->IsFocusableNode()) {
1651         return lastFocusNode->PaintAllFocusState();
1652     }
1653     if (onPaintFocusStateCallback_) {
1654         return onPaintFocusStateCallback_();
1655     }
1656     if (focusStyleType_ != FocusStyleType::NONE) {
1657         return false;
1658     }
1659 
1660     // Force paint focus box for the component on the tail of focus-chain.
1661     // This is designed for the focus-chain that all components' focus style are none.
1662     if (IsViewRootScope()) {
1663         return !isFocusActiveWhenFocused_;
1664     }
1665     focusStyleType_ = FocusStyleType::FORCE_BORDER;
1666     if (PaintFocusState()) {
1667         RaiseZIndex();
1668     }
1669     focusManager->SetLastFocusStateNode(AceType::Claim(this));
1670     return !isFocusActiveWhenFocused_;
1671 }
1672 
PaintInnerFocusState(const RoundRect & paintRect,bool forceUpdate)1673 bool FocusHub::PaintInnerFocusState(const RoundRect& paintRect, bool forceUpdate)
1674 {
1675     auto context = PipelineContext::GetCurrentContextSafely();
1676     CHECK_NULL_RETURN(context, false);
1677     auto frameNode = GetFrameNode();
1678     CHECK_NULL_RETURN(frameNode, false);
1679     auto renderContext = frameNode->GetRenderContext();
1680     CHECK_NULL_RETURN(renderContext, false);
1681     if (!forceUpdate && (!context->GetIsFocusActive() || !IsNeedPaintFocusState())) {
1682         return false;
1683     }
1684     auto appTheme = context->GetTheme<AppTheme>();
1685     CHECK_NULL_RETURN(appTheme, false);
1686     Color paintColor;
1687     if (box_.paintStyle_ && box_.paintStyle_->strokeColor) {
1688         paintColor = box_.paintStyle_->strokeColor.value();
1689     } else if (HasPaintColor()) {
1690         paintColor = GetPaintColor();
1691     } else {
1692         paintColor = appTheme->GetFocusColor();
1693     }
1694     Dimension paintWidth;
1695     if (box_.paintStyle_ && box_.paintStyle_->strokeWidth) {
1696         paintWidth = box_.paintStyle_->strokeWidth.value();
1697     } else if (HasPaintWidth()) {
1698         paintWidth = GetPaintWidth();
1699     } else {
1700         paintWidth = appTheme->GetFocusWidthVp();
1701     }
1702     renderContext->ClearFocusState();
1703     if (NEAR_ZERO(paintWidth.Value())) {
1704         return true;
1705     }
1706     renderContext->PaintFocusState(paintRect, paintColor, paintWidth);
1707     return true;
1708 }
1709 
ClearFocusState(bool isNeedStateStyles)1710 void FocusHub::ClearFocusState(bool isNeedStateStyles)
1711 {
1712     if (isNeedStateStyles) {
1713         // check focus state style.
1714         CheckFocusStateStyle(false);
1715     }
1716     if (onClearFocusStateCallback_) {
1717         onClearFocusStateCallback_();
1718     }
1719     if (focusStyleType_ != FocusStyleType::NONE) {
1720         auto frameNode = GetFrameNode();
1721         CHECK_NULL_VOID(frameNode);
1722         auto renderContext = frameNode->GetRenderContext();
1723         CHECK_NULL_VOID(renderContext);
1724         if (isRaisedZIndex_) {
1725             renderContext->ResetZIndex();
1726             renderContext->OnZIndexUpdate(0);
1727             isRaisedZIndex_ = false;
1728         }
1729         renderContext->ClearFocusState();
1730     }
1731 }
1732 
ClearAllFocusState()1733 void FocusHub::ClearAllFocusState()
1734 {
1735     ClearFocusState();
1736     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
1737     if (lastFocusNode) {
1738         lastFocusNode->ClearAllFocusState();
1739     }
1740     if (focusStyleType_ == FocusStyleType::FORCE_BORDER) {
1741         focusStyleType_ = FocusStyleType::NONE;
1742     }
1743 }
1744 
IsNeedPaintFocusState()1745 bool FocusHub::IsNeedPaintFocusState()
1746 {
1747     if (currentFocus_ && IsFocusableNode() &&
1748         (focusDepend_ == FocusDependence::SELF || focusType_ == FocusType::NODE)) {
1749         return focusStyleType_ != FocusStyleType::NONE || HasFocusStateStyle();
1750     }
1751     auto lastFocusNode = GetLastWeakFocusNode().Upgrade();
1752     while (lastFocusNode) {
1753         if (!lastFocusNode->IsCurrentFocus() || !lastFocusNode->IsFocusableNode()) {
1754             break;
1755         }
1756         if (lastFocusNode->GetFocusStyleType() != FocusStyleType::NONE || lastFocusNode->HasFocusStateStyle()) {
1757             return false;
1758         }
1759         lastFocusNode = lastFocusNode->GetLastWeakFocusNode().Upgrade();
1760     }
1761     return focusStyleType_ != FocusStyleType::NONE || HasFocusStateStyle();
1762 }
1763 
AcceptFocusOfSpecifyChild(FocusStep step)1764 bool FocusHub::AcceptFocusOfSpecifyChild(FocusStep step)
1765 {
1766     if (focusType_ == FocusType::NODE) {
1767         return IsFocusable();
1768     }
1769     if (focusType_ != FocusType::SCOPE || !IsFocusableScope()) {
1770         return false;
1771     }
1772     if (focusDepend_ == FocusDependence::SELF) {
1773         return true;
1774     }
1775     if (IsFocusStepTab(step) && AcceptFocusOfPriorityChild()) {
1776         return true;
1777     }
1778 
1779     auto operation = [this, step](const RefPtr<FocusHub>& focusHub) {
1780         if (focusHub && focusHub->AcceptFocusOfSpecifyChild(step)) {
1781             lastWeakFocusNode_ = focusHub;
1782             return true;
1783         }
1784         return false;
1785     };
1786     bool canChildBeFocused = false;
1787     if (step == FocusStep::TAB) {
1788         canChildBeFocused = AnyChildFocusHub<false>(operation);
1789     } else if (step == FocusStep::SHIFT_TAB) {
1790         canChildBeFocused = AnyChildFocusHub<true>(operation);
1791     } else {
1792         LOGI("Invalid focus step: %{public}d for %{public}s/%{public}d specify focus child.", step,
1793             GetFrameName().c_str(), GetFrameId());
1794     }
1795     if (focusDepend_ == FocusDependence::CHILD) {
1796         return canChildBeFocused;
1797     }
1798     return focusDepend_ == FocusDependence::AUTO;
1799 }
1800 
AcceptFocusOfLastFocus()1801 bool FocusHub::AcceptFocusOfLastFocus()
1802 {
1803     if (focusType_ == FocusType::SCOPE) {
1804         auto lastFocusNode = lastWeakFocusNode_.Upgrade();
1805         return lastFocusNode ? lastFocusNode->AcceptFocusOfLastFocus() : false;
1806     }
1807     if (focusType_ == FocusType::NODE) {
1808         return IsFocusableWholePath();
1809     }
1810     return false;
1811 }
1812 
AcceptFocusByRectOfLastFocus(const RectF & rect)1813 bool FocusHub::AcceptFocusByRectOfLastFocus(const RectF& rect)
1814 {
1815     if (focusType_ == FocusType::NODE) {
1816         return AcceptFocusByRectOfLastFocusNode(rect);
1817     }
1818     if (focusType_ == FocusType::SCOPE) {
1819         return AcceptFocusByRectOfLastFocusFlex(rect);
1820     }
1821     return false;
1822 }
1823 
AcceptFocusByRectOfLastFocusNode(const RectF & rect)1824 bool FocusHub::AcceptFocusByRectOfLastFocusNode(const RectF& rect)
1825 {
1826     return IsFocusableWholePath();
1827 }
1828 
AcceptFocusByRectOfLastFocusFlex(const RectF & rect)1829 bool FocusHub::AcceptFocusByRectOfLastFocusFlex(const RectF& rect)
1830 {
1831     if (!rect.IsValid()) {
1832         return false;
1833     }
1834 
1835     if (focusType_ != FocusType::SCOPE || !IsFocusableWholePath()) {
1836         return false;
1837     }
1838     if (focusDepend_ == FocusDependence::SELF) {
1839         return true;
1840     }
1841     if (AcceptFocusOfPriorityChild()) {
1842         return true;
1843     }
1844     bool canChildBeFocused = false;
1845     OffsetF offset;
1846     RefPtr<FocusHub> newFocusNode;
1847     double minVal = std::numeric_limits<double>::max();
1848     AllChildFocusHub([this, &rect, &offset, &newFocusNode, &minVal](const RefPtr<FocusHub>& child) {
1849         if (!child->IsFocusable()) {
1850             return;
1851         }
1852 
1853         RectF childRect;
1854         if (!CalculateRect(child, childRect)) {
1855             return;
1856         }
1857         if (!childRect.IsValid() || NearZero(childRect.Width()) || NearZero(childRect.Height())) {
1858             return;
1859         }
1860         OffsetF vec = childRect.Center() - rect.Center();
1861         double val = (vec.GetX() * vec.GetX()) + (vec.GetY() * vec.GetY());
1862         if (minVal > val) {
1863             minVal = val;
1864             newFocusNode = child;
1865             offset = childRect.GetOffset();
1866         }
1867     });
1868 
1869     if (newFocusNode && newFocusNode->AcceptFocusByRectOfLastFocus(rect - offset)) {
1870         lastWeakFocusNode_ = newFocusNode;
1871         canChildBeFocused = true;
1872     }
1873     if (focusDepend_ == FocusDependence::CHILD) {
1874         return canChildBeFocused;
1875     }
1876     return focusDepend_ == FocusDependence::AUTO;
1877 }
1878 
CalculateRect(const RefPtr<FocusHub> & childNode,RectF & rect) const1879 bool FocusHub::CalculateRect(const RefPtr<FocusHub>& childNode, RectF& rect) const
1880 {
1881     auto frameNode = childNode->GetFrameNode();
1882     CHECK_NULL_RETURN(frameNode, false);
1883     rect = frameNode->GetPaintRectWithTransform();
1884 
1885     //  Calculate currentNode -> childNode offset
1886     auto parent = frameNode->GetAncestorNodeOfFrame();
1887     while (parent && parent != GetFrameNode()) {
1888         rect += parent->GetPaintRectWithTransform().GetOffset();
1889         parent = parent->GetAncestorNodeOfFrame();
1890     }
1891     return true;
1892 }
1893 
IsFocusableByTab()1894 bool FocusHub::IsFocusableByTab()
1895 {
1896     if (focusType_ == FocusType::NODE) {
1897         return IsFocusableNodeByTab();
1898     }
1899     if (focusType_ == FocusType::SCOPE) {
1900         return IsFocusableScopeByTab();
1901     }
1902     return false;
1903 }
1904 
IsFocusableNodeByTab()1905 bool FocusHub::IsFocusableNodeByTab()
1906 {
1907     auto parent = GetParentFocusHub();
1908     CHECK_NULL_RETURN(parent, GetTabIndex() == 0);
1909     return (GetTabIndex() == 0) && (parent->GetTabIndex() == 0);
1910 }
1911 
IsFocusableScopeByTab()1912 bool FocusHub::IsFocusableScopeByTab()
1913 {
1914     if (!IsFocusableNodeByTab()) {
1915         return false;
1916     }
1917     bool hasChild = false;
1918     return AnyChildFocusHub([&hasChild](const RefPtr<FocusHub>& focusNode) {
1919         hasChild = true;
1920         return focusNode->IsFocusableByTab();
1921     }) || !hasChild;
1922 }
1923 
IsFocusableWholePath()1924 bool FocusHub::IsFocusableWholePath()
1925 {
1926     auto parent = GetParentFocusHub();
1927     while (parent) {
1928         if (!parent->IsFocusableNode()) {
1929             return false;
1930         }
1931         parent = parent->GetParentFocusHub();
1932     }
1933     return IsFocusable();
1934 }
1935 
GetUnfocusableParentFocusNode()1936 WeakPtr<FocusHub> FocusHub::GetUnfocusableParentFocusNode()
1937 {
1938     if (!IsFocusable()) {
1939         return AceType::WeakClaim(this);
1940     }
1941     auto parent = GetParentFocusHub();
1942     while (parent) {
1943         if (!parent->IsFocusableNode()) {
1944             return AceType::WeakClaim(AceType::RawPtr(parent));
1945         }
1946         parent = parent->GetParentFocusHub();
1947     }
1948     return nullptr;
1949 }
1950 
IsSelfFocusableWholePath()1951 bool FocusHub::IsSelfFocusableWholePath()
1952 {
1953     auto parent = GetParentFocusHub();
1954     while (parent) {
1955         if (!parent->IsFocusableNode()) {
1956             return false;
1957         }
1958         parent = parent->GetParentFocusHub();
1959     }
1960     return IsFocusableNode();
1961 }
1962 
IsOnRootTree() const1963 bool FocusHub::IsOnRootTree() const
1964 {
1965     auto parent = GetParentFocusHub();
1966     while (parent) {
1967         auto parentName = parent->GetFrameName();
1968         if (parentName == V2::ROOT_ETS_TAG) {
1969             return true;
1970         }
1971         parent = parent->GetParentFocusHub();
1972     }
1973     return false;
1974 }
1975 
CollectTabIndexNodes(TabIndexNodeList & tabIndexNodes)1976 void FocusHub::CollectTabIndexNodes(TabIndexNodeList& tabIndexNodes)
1977 {
1978     if (GetTabIndex() > 0 && IsFocusableWholePath()) {
1979         tabIndexNodes.emplace_back(GetTabIndex(), WeakClaim(this));
1980     }
1981     if (GetFocusType() == FocusType::SCOPE) {
1982         AllChildFocusHub([&tabIndexNodes](const RefPtr<FocusHub>& child) {
1983             child->CollectTabIndexNodes(tabIndexNodes);
1984         });
1985     }
1986 }
1987 
GoToFocusByTabNodeIdx(TabIndexNodeList & tabIndexNodes,int32_t tabNodeIdx)1988 bool FocusHub::GoToFocusByTabNodeIdx(TabIndexNodeList& tabIndexNodes, int32_t tabNodeIdx)
1989 {
1990     auto iter = tabIndexNodes.begin();
1991     std::advance(iter, tabNodeIdx);
1992     if (iter == tabIndexNodes.end()) {
1993         return false;
1994     }
1995     auto nodeNeedToFocus = (*iter).second.Upgrade();
1996     if (!nodeNeedToFocus) {
1997         TAG_LOGW(AceLogTag::ACE_FOCUS, "Tab index node is null");
1998         return false;
1999     }
2000     auto nodeIdNeedToFocus = nodeNeedToFocus->GetFrameId();
2001     TAG_LOGI(AceLogTag::ACE_FOCUS, "Move focus to tab index node %{public}d: %{public}s/" SEC_PLD(%{public}d),
2002         tabNodeIdx, nodeNeedToFocus->GetFrameName().c_str(), SEC_PARAM(nodeNeedToFocus->GetFrameId()));
2003     if (nodeNeedToFocus->GetFocusType() == FocusType::SCOPE && !nodeNeedToFocus->IsDefaultGroupHasFocused()) {
2004         auto defaultFocusNode = nodeNeedToFocus->GetChildFocusNodeByType(FocusNodeType::GROUP_DEFAULT);
2005         if (defaultFocusNode) {
2006             if (!defaultFocusNode->IsFocusableWholePath()) {
2007                 TAG_LOGI(AceLogTag::ACE_FOCUS, "node(%{public}d) is not focusable", tabNodeIdx);
2008                 return false;
2009             }
2010             nodeNeedToFocus->SetIsDefaultGroupHasFocused(true);
2011             if (defaultFocusNode->RequestFocusImmediatelyInner()) {
2012                 lastTabIndexNodeId_ = nodeIdNeedToFocus;
2013                 return true;
2014             }
2015             return false;
2016         }
2017     }
2018     if (!nodeNeedToFocus->IsFocusableWholePath()) {
2019         TAG_LOGI(AceLogTag::ACE_FOCUS, "node(%{public}d) is not focusable", tabNodeIdx);
2020         return false;
2021     }
2022     if (nodeNeedToFocus->RequestFocusImmediatelyInner()) {
2023         lastTabIndexNodeId_ = nodeIdNeedToFocus;
2024         return true;
2025     }
2026     return false;
2027 }
2028 
GetChildFocusNodeByType(FocusNodeType nodeType)2029 RefPtr<FocusHub> FocusHub::GetChildFocusNodeByType(FocusNodeType nodeType)
2030 {
2031     if (nodeType == FocusNodeType::DEFAULT && IsDefaultFocus() && IsFocusable()) {
2032         return AceType::Claim(this);
2033     }
2034     if (nodeType == FocusNodeType::GROUP_DEFAULT && IsDefaultGroupFocus() && IsFocusable()) {
2035         return AceType::Claim(this);
2036     }
2037     if (focusType_ != FocusType::SCOPE) {
2038         return nullptr;
2039     }
2040     RefPtr<FocusHub> target;
2041     AnyChildFocusHub([&target, nodeType](const RefPtr<FocusHub>& child) {
2042         if (!child) {
2043             return false;
2044         }
2045         auto childFrame = child->GetFrameNode();
2046         if (!childFrame) {
2047             return false;
2048         }
2049         auto childFocusView = childFrame->GetPattern<FocusView>();
2050         if (childFocusView && childFocusView->IsFocusViewLegal() && childFocusView->IsEntryFocusView()) {
2051             return false;
2052         }
2053         target = child->GetChildFocusNodeByType(nodeType);
2054         return target ? true : false;
2055     });
2056     return target;
2057 }
2058 
GetChildFocusNodeById(const std::string & id)2059 RefPtr<FocusHub> FocusHub::GetChildFocusNodeById(const std::string& id)
2060 {
2061     if (id.empty()) {
2062         return nullptr;
2063     }
2064     if (GetInspectorKey().has_value() && GetInspectorKey().value() == id) {
2065         return AceType::Claim(this);
2066     }
2067     RefPtr<FocusHub> target;
2068     if (focusType_ == FocusType::SCOPE) {
2069         AnyChildFocusHub([&target, &id](const RefPtr<FocusHub>& child) {
2070             target = child->GetChildFocusNodeById(id);
2071             return target ? true : false;
2072         });
2073     }
2074     return target;
2075 }
2076 
GetFirstChildFocusView()2077 RefPtr<FocusView> FocusHub::GetFirstChildFocusView()
2078 {
2079     auto frameNode = GetFrameNode();
2080     CHECK_NULL_RETURN(frameNode, nullptr);
2081     auto focusView = frameNode->GetPattern<FocusView>();
2082     if (focusView) {
2083         return focusView;
2084     }
2085     AnyChildFocusHub<true>(
2086         [&focusView](const RefPtr<FocusHub>& childFocusHub) {
2087             if (!childFocusHub) {
2088                 return false;
2089             }
2090             focusView = childFocusHub->GetFirstChildFocusView();
2091             return focusView ? true : false;
2092         });
2093     return focusView;
2094 }
2095 
TriggerFocusScroll()2096 bool FocusHub::TriggerFocusScroll()
2097 {
2098     auto frameNode = GetFrameNode();
2099     CHECK_NULL_RETURN(frameNode, false);
2100     auto* context = frameNode->GetContext();
2101     CHECK_NULL_RETURN(context, false);
2102     if (!context->GetIsFocusActive() || (focusType_ == FocusType::DISABLE && !isFocusUnit_)) {
2103         return false;
2104     }
2105     return ScrollByOffset();
2106 }
2107 
ScrollByOffset()2108 bool FocusHub::ScrollByOffset()
2109 {
2110     auto parent = GetParentFocusHub();
2111     RefPtr<FrameNode> parentFrame;
2112     RefPtr<Pattern> parentPattern;
2113     bool ret = false;
2114     while (parent) {
2115         if (parent->isFocusUnit_) {
2116             return false;
2117         }
2118         parentFrame = parent->GetFrameNode();
2119         if (!parentFrame) {
2120             parent = parent->GetParentFocusHub();
2121             continue;
2122         }
2123         if (ScrollByOffsetToParent(parentFrame)) {
2124             ret = true;
2125         }
2126         parent = parent->GetParentFocusHub();
2127     }
2128     return ret;
2129 }
2130 
ScrollByOffsetToParent(const RefPtr<FrameNode> & parentFrameNode) const2131 bool FocusHub::ScrollByOffsetToParent(const RefPtr<FrameNode>& parentFrameNode) const
2132 {
2133     auto curFrameNode = GetFrameNode();
2134     CHECK_NULL_RETURN(curFrameNode, false);
2135     CHECK_NULL_RETURN(parentFrameNode, false);
2136     auto parentPattern = parentFrameNode->GetPattern<ScrollablePattern>();
2137     CHECK_NULL_RETURN(parentPattern, false);
2138 
2139     auto scrollAbility = parentPattern->GetScrollOffsetAbility();
2140     auto scrollFunc = scrollAbility.scrollFunc;
2141     auto scrollAxis = scrollAbility.axis;
2142     if (!scrollFunc || scrollAxis == Axis::NONE) {
2143         return false;
2144     }
2145     auto moveOffset = ScrollableUtils::GetMoveOffset(parentFrameNode, curFrameNode, scrollAxis == Axis::VERTICAL,
2146         scrollAbility.contentStartOffset, scrollAbility.contentEndOffset);
2147     if (!NearZero(moveOffset)) {
2148         TAG_LOGI(AceLogTag::ACE_FOCUS, "Scroll offset: %{public}f on %{public}s/%{public}d, axis: %{public}d",
2149             moveOffset, parentFrameNode->GetTag().c_str(), parentFrameNode->GetId(), scrollAxis);
2150         auto ret = scrollFunc(parentPattern->IsReverse() ? -moveOffset : moveOffset);
2151         auto pipeline = PipelineContext::GetCurrentContext();
2152         if (pipeline) {
2153             pipeline->FlushUITasks();
2154         }
2155         return ret;
2156     }
2157     return false;
2158 }
2159 
RequestFocusImmediatelyById(const std::string & id,bool isSyncRequest)2160 bool FocusHub::RequestFocusImmediatelyById(const std::string& id, bool isSyncRequest)
2161 {
2162     auto node = GetFrameNode();
2163     CHECK_NULL_RETURN(node, false);
2164     auto pipeline = node->GetContextRefPtr();
2165     CHECK_NULL_RETURN(pipeline, false);
2166     auto focusManager = pipeline->GetOrCreateFocusManager();
2167     CHECK_NULL_RETURN(focusManager, false);
2168     auto focusNode = GetChildFocusNodeById(id);
2169     if (!focusNode) {
2170         TAG_LOGI(AceLogTag::ACE_FOCUS, "Request focus id can not found.");
2171         focusManager->TriggerRequestFocusCallback(RequestFocusResult::NON_EXIST);
2172         return false;
2173     }
2174     auto result = true;
2175     if ((isSyncRequest && !focusNode->IsSyncRequestFocusable()) ||
2176         (!isSyncRequest && !focusNode->IsFocusable())) {
2177         result = false;
2178     }
2179     TAG_LOGI(AceLogTag::ACE_FOCUS,
2180         "Request focus immediately %{public}s by id. The node is %{public}s/" SEC_PLD(%{public}d),
2181         isSyncRequest ? " sync" : " async", focusNode->GetFrameName().c_str(), SEC_PARAM(focusNode->GetFrameId()));
2182     if (result || !isSyncRequest) {
2183         pipeline->AddDirtyRequestFocus(focusNode->GetFrameNode());
2184         if (isSyncRequest) {
2185             focusNode->SetLastWeakFocusNodeToPreviousNode();
2186             pipeline->FlushRequestFocus();
2187         }
2188     }
2189     return result;
2190 }
2191 
GetFocusingTabNodeIdx(TabIndexNodeList & tabIndexNodes) const2192 int32_t FocusHub::GetFocusingTabNodeIdx(TabIndexNodeList& tabIndexNodes) const
2193 {
2194     if (lastTabIndexNodeId_ == DEFAULT_TAB_FOCUSED_INDEX) {
2195         return DEFAULT_TAB_FOCUSED_INDEX;
2196     }
2197     int32_t i = 0;
2198     for (auto& wpNode : tabIndexNodes) {
2199         auto node = wpNode.second.Upgrade();
2200         if (node && node->IsCurrentFocus() && node->GetFrameId() == lastTabIndexNodeId_) {
2201             return i;
2202         }
2203         ++i;
2204     }
2205     return DEFAULT_TAB_FOCUSED_INDEX;
2206 }
2207 
HandleFocusByTabIndex(const KeyEvent & event)2208 bool FocusHub::HandleFocusByTabIndex(const KeyEvent& event)
2209 {
2210     if (event.code != KeyCode::KEY_TAB || event.action != KeyAction::DOWN) {
2211         return false;
2212     }
2213     auto node = GetFrameNode();
2214     CHECK_NULL_RETURN(node, false);
2215     auto pipeline = node->GetContextRefPtr();
2216     if (pipeline && pipeline->IsTabJustTriggerOnKeyEvent()) {
2217         return false;
2218     }
2219     TabIndexNodeList tabIndexNodes;
2220     tabIndexNodes.clear();
2221     CollectTabIndexNodes(tabIndexNodes);
2222     if (tabIndexNodes.empty()) {
2223         return false;
2224     }
2225     tabIndexNodes.sort([](std::pair<int32_t, WeakPtr<FocusHub>>& a, std::pair<int32_t, WeakPtr<FocusHub>>& b) {
2226         return a.first < b.first;
2227     });
2228     int32_t curTabFocusIndex = GetFocusingTabNodeIdx(tabIndexNodes);
2229     if ((curTabFocusIndex < 0 || curTabFocusIndex >= static_cast<int32_t>(tabIndexNodes.size())) &&
2230         curTabFocusIndex != DEFAULT_TAB_FOCUSED_INDEX) {
2231         TAG_LOGI(AceLogTag::ACE_FOCUS, "Current focused tabIndex: %{public}d is not valid. Use default focus system.",
2232             curTabFocusIndex);
2233         return false;
2234     }
2235     if (curTabFocusIndex == DEFAULT_TAB_FOCUSED_INDEX) {
2236         curTabFocusIndex = 0;
2237     } else {
2238         if (event.IsShiftWith(KeyCode::KEY_TAB)) {
2239             --curTabFocusIndex;
2240         } else {
2241             ++curTabFocusIndex;
2242         }
2243         if (curTabFocusIndex < 0 || curTabFocusIndex >= static_cast<int32_t>(tabIndexNodes.size())) {
2244             curTabFocusIndex = (curTabFocusIndex + static_cast<int32_t>(tabIndexNodes.size())) %
2245                                static_cast<int32_t>(tabIndexNodes.size());
2246         }
2247     }
2248     return GoToFocusByTabNodeIdx(tabIndexNodes, curTabFocusIndex);
2249 }
2250 
HasBackwardFocusMovementInChildren()2251 bool FocusHub::HasBackwardFocusMovementInChildren()
2252 {
2253     return AnyChildFocusHub([](const RefPtr<FocusHub>& child) { return child->HasBackwardFocusMovement(); });
2254 }
2255 
HasForwardFocusMovementInChildren()2256 bool FocusHub::HasForwardFocusMovementInChildren()
2257 {
2258     return AnyChildFocusHub([](const RefPtr<FocusHub>& child) { return child->HasForwardFocusMovement(); });
2259 }
2260 
ClearFocusMovementFlagsInChildren()2261 void FocusHub::ClearFocusMovementFlagsInChildren()
2262 {
2263     AllChildFocusHub([](const RefPtr<FocusHub>& child) {
2264         child->ClearFocusMovementFlags();
2265         child->ClearFocusMovementFlagsInChildren();
2266     });
2267 }
2268 
GetProjectAreaOnRect(const RectF & rect,const RectF & projectRect,FocusStep step)2269 double FocusHub::GetProjectAreaOnRect(const RectF& rect, const RectF& projectRect, FocusStep step)
2270 {
2271     float areaWidth = 0.0;
2272     float areaHeight = 0.0;
2273     switch (step) {
2274         case FocusStep::UP:
2275             if (rect.Top() < projectRect.Bottom() && rect.Right() > projectRect.Left() &&
2276                 rect.Left() < projectRect.Right()) {
2277                 areaWidth = std::min(rect.Right(), projectRect.Right()) - std::max(rect.Left(), projectRect.Left());
2278                 areaHeight = std::min(rect.Bottom(), projectRect.Bottom()) - rect.Top();
2279             }
2280             break;
2281         case FocusStep::DOWN:
2282             if (rect.Bottom() > projectRect.Top() && rect.Right() > projectRect.Left() &&
2283                 rect.Left() < projectRect.Right()) {
2284                 areaWidth = std::min(rect.Right(), projectRect.Right()) - std::max(rect.Left(), projectRect.Left());
2285                 areaHeight = rect.Bottom() - std::max(rect.Top(), projectRect.Top());
2286             }
2287             break;
2288         case FocusStep::LEFT:
2289             if (rect.Left() < projectRect.Right() && rect.Bottom() > projectRect.Top() &&
2290                 rect.Top() < projectRect.Bottom()) {
2291                 areaWidth = std::min(rect.Right(), projectRect.Right()) - rect.Left();
2292                 areaHeight = std::min(rect.Bottom(), projectRect.Bottom()) - std::max(rect.Top(), projectRect.Top());
2293             }
2294             break;
2295         case FocusStep::RIGHT:
2296             if (rect.Right() > projectRect.Left() && rect.Bottom() > projectRect.Top() &&
2297                 rect.Top() < projectRect.Bottom()) {
2298                 areaWidth = rect.Right() - std::max(rect.Left(), projectRect.Left());
2299                 areaHeight = std::min(rect.Bottom(), projectRect.Bottom()) - std::max(rect.Top(), projectRect.Top());
2300             }
2301             break;
2302         default:
2303             break;
2304     }
2305     return areaWidth * areaHeight;
2306 }
2307 
GetNearestNodeByProjectArea(const std::list<RefPtr<FocusHub>> & allNodes,FocusStep step)2308 RefPtr<FocusHub> FocusHub::GetNearestNodeByProjectArea(const std::list<RefPtr<FocusHub>>& allNodes, FocusStep step)
2309 {
2310     CHECK_NULL_RETURN(!allNodes.empty(), nullptr);
2311     auto curFrameNode = GetFrameNode();
2312     CHECK_NULL_RETURN(curFrameNode, nullptr);
2313     auto curFrameOffset = curFrameNode->GetTransformRelativeOffset();
2314     auto curGeometryNode = curFrameNode->GetGeometryNode();
2315     CHECK_NULL_RETURN(curGeometryNode, nullptr);
2316     RectF curFrameRect = RectF(curFrameOffset, curGeometryNode->GetFrameRect().GetSize());
2317     curFrameRect.SetOffset(curFrameOffset);
2318     TAG_LOGD(AceLogTag::ACE_FOCUS,
2319         "Current focus node is %{public}s/%{public}d. Rect is {%{public}f,%{public}f,%{public}f,%{public}f}.",
2320         GetFrameName().c_str(), GetFrameId(), curFrameRect.Left(), curFrameRect.Top(), curFrameRect.Right(),
2321         curFrameRect.Bottom());
2322     bool isTabStep = IsFocusStepTab(step);
2323     double resDistance = !isTabStep ? std::numeric_limits<double>::max() : 0.0f;
2324     bool isRtl = AceApplicationInfo::GetInstance().IsRightToLeft();
2325     RefPtr<FocusHub> nextNode;
2326     for (const auto& node : allNodes) {
2327         if (!node || AceType::RawPtr(node) == this) {
2328             continue;
2329         }
2330         auto frameNode = node->GetFrameNode();
2331         if (!frameNode) {
2332             continue;
2333         }
2334         auto frameOffset = frameNode->GetTransformRelativeOffset();
2335         auto geometryNode = frameNode->GetGeometryNode();
2336         if (!geometryNode) {
2337             continue;
2338         }
2339         if (!node->IsFocusable()) {
2340             continue;
2341         }
2342         RectF frameRect = RectF(frameOffset, geometryNode->GetFrameRect().GetSize());
2343         auto realStep = step;
2344         if (step == FocusStep::TAB) {
2345             frameRect -= OffsetF(0, curFrameRect.Height());
2346             // If TAB step, for RTL, the direction of focus is RIGHT.
2347             // If TAB step, for LTR, the direction of focus is LEFT.
2348             realStep = isRtl ? FocusStep::RIGHT : FocusStep::LEFT;
2349         } else if (step == FocusStep::SHIFT_TAB) {
2350             frameRect += OffsetF(0, curFrameRect.Height());
2351             // If SHIFT_TAB step, for RTL, the direction of focus is LEFT.
2352             // If SHIFT_TAB step, for LTR, the direction of focus is RIGHT.
2353             realStep = isRtl ? FocusStep::LEFT : FocusStep::RIGHT;
2354         }
2355         auto projectArea = GetProjectAreaOnRect(frameRect, curFrameRect, realStep);
2356         if (Positive(projectArea)) {
2357             OffsetF vec = frameRect.Center() - curFrameRect.Center();
2358             double val = (vec.GetX() * vec.GetX()) + (vec.GetY() * vec.GetY());
2359             // The operation direction is opposite for RTL languages.
2360             if ((step == FocusStep::TAB && (isRtl ? Negative(vec.GetX()) : Positive(vec.GetX()))) ||
2361                 (step == FocusStep::SHIFT_TAB && (isRtl ? Positive(vec.GetX()) : Negative(vec.GetX())))) {
2362                 val *= -1.0;
2363             }
2364             if ((!isTabStep && val < resDistance) || (isTabStep && val > resDistance)) {
2365                 resDistance = val;
2366                 nextNode = node;
2367             }
2368         }
2369     }
2370     TAG_LOGD(AceLogTag::ACE_FOCUS, "Current focus node is %{public}s/" SEC_PLD(%{public}d)
2371         " Next focus node is %{public}s/" SEC_PLD(%{public}d) ". Min distance is %{public}f.",
2372         GetFrameName().c_str(), SEC_PARAM(GetFrameId()),
2373         nextNode ? nextNode->GetFrameName().c_str() : "NULL",
2374         SEC_PARAM(nextNode ? nextNode->GetFrameId() : -1), resDistance);
2375     return nextNode;
2376 }
2377 
UpdateFocusView()2378 bool FocusHub::UpdateFocusView()
2379 {
2380     CHECK_NULL_RETURN(IsCurrentFocus(), false);
2381     auto frameNode = GetFrameNode();
2382     CHECK_NULL_RETURN(frameNode, false);
2383     auto focusView = frameNode->GetPattern<FocusView>();
2384     if (!focusView) {
2385         if (frameNode->IsOnMainTree()) {
2386             auto focusManager = GetFocusManager();
2387             CHECK_NULL_RETURN(focusManager, false);
2388             focusManager->FlushFocusView();
2389         }
2390         return true;
2391     }
2392     auto focusedChild = lastWeakFocusNode_.Upgrade();
2393     while (focusedChild) {
2394         auto focusedChildFrame = focusedChild->GetFrameNode();
2395         if (!focusedChildFrame) {
2396             focusedChild = focusedChild->lastWeakFocusNode_.Upgrade();
2397             continue;
2398         }
2399         auto focusedChildFocusView = focusedChildFrame->GetPattern<FocusView>();
2400         if (focusedChildFocusView) {
2401             return false;
2402         }
2403         focusedChild = focusedChild->lastWeakFocusNode_.Upgrade();
2404     }
2405     auto curFocusView = FocusView::GetCurrentFocusView();
2406     if (focusView && focusView->IsFocusViewLegal() && focusView != curFocusView) {
2407         auto focusViewRootScope = focusView->GetViewRootScope();
2408         auto focusViewRootScopeChild = focusViewRootScope ? focusViewRootScope->lastWeakFocusNode_.Upgrade() : nullptr;
2409         if (focusViewRootScopeChild && focusViewRootScopeChild->IsCurrentFocus()) {
2410             focusView->SetIsViewRootScopeFocused(false);
2411         }
2412         TAG_LOGD(AceLogTag::ACE_FOCUS, "UpdateFocusView by node %{public}s/" SEC_PLD(%{public}d),
2413             GetFrameName().c_str(), SEC_PARAM(GetFrameId()));
2414         focusView->FocusViewShow(true);
2415     }
2416     return true;
2417 }
2418 
SetFocusScopeId(const std::string & focusScopeId,bool isGroup,bool arrowKeyStepOut)2419 void FocusHub::SetFocusScopeId(const std::string& focusScopeId, bool isGroup, bool arrowKeyStepOut)
2420 {
2421     if (focusType_ != FocusType::SCOPE) {
2422         return;
2423     }
2424     auto focusManager = GetFocusManager();
2425     if (focusScopeId.empty()) {
2426         if (!focusScopeId_.empty() && focusManager) {
2427             focusManager->RemoveFocusScope(focusScopeId_);
2428         }
2429         focusScopeId_ = focusScopeId;
2430         isFocusScope_ = false;
2431         isGroup_ = false;
2432         arrowKeyStepOut_ = true;
2433         return;
2434     }
2435     if (focusManager && !focusManager->AddFocusScope(focusScopeId, AceType::Claim(this))) {
2436         TAG_LOGW(AceLogTag::ACE_FOCUS, "node(%{public}s/%{public}d) focusScopeId exist.", GetFrameName().c_str(),
2437             GetFrameId());
2438         bool isValidFocusScope = (isFocusScope_ && !focusScopeId_.empty());
2439         if (isValidFocusScope) {
2440             isGroup_ = isGroup;
2441             arrowKeyStepOut_ = arrowKeyStepOut;
2442         }
2443         return;
2444     }
2445     focusScopeId_ = focusScopeId;
2446     isFocusScope_ = true;
2447     isGroup_ = isGroup;
2448     arrowKeyStepOut_ = arrowKeyStepOut;
2449 }
2450 
RemoveFocusScopeIdAndPriority()2451 void FocusHub::RemoveFocusScopeIdAndPriority()
2452 {
2453     auto focusManager = GetFocusManager();
2454     if (isFocusScope_) {
2455         if (!focusScopeId_.empty() && focusManager) {
2456             focusManager->RemoveFocusScope(focusScopeId_);
2457         }
2458     } else {
2459         if (focusPriority_ != FocusPriority::AUTO && !focusScopeId_.empty() && focusManager) {
2460             focusManager->RemoveScopePriorityNode(focusScopeId_, AceType::Claim(this));
2461         }
2462     }
2463 }
2464 
SetFocusScopePriority(const std::string & focusScopeId,const uint32_t focusPriority)2465 void FocusHub::SetFocusScopePriority(const std::string& focusScopeId, const uint32_t focusPriority)
2466 {
2467     if (isFocusScope_) {
2468         TAG_LOGW(AceLogTag::ACE_FOCUS, "FocusScope can not set focusPriority");
2469         return;
2470     }
2471     auto focusManager = GetFocusManager();
2472     if (focusScopeId.empty()) {
2473         if (!focusScopeId_.empty() && focusManager) {
2474             focusManager->RemoveScopePriorityNode(focusScopeId_, AceType::Claim(this));
2475         }
2476         focusScopeId_ = focusScopeId;
2477         focusPriority_ = FocusPriority::AUTO;
2478         return;
2479     }
2480     if (!focusScopeId_.empty() && focusScopeId_ != focusScopeId && focusManager) {
2481         focusManager->RemoveScopePriorityNode(focusScopeId_, AceType::Claim(this));
2482     }
2483 
2484     if (focusPriority == static_cast<uint32_t>(FocusPriority::PRIOR)) {
2485         focusPriority_ = FocusPriority::PRIOR;
2486         if (focusManager) {
2487             focusManager->AddScopePriorityNode(focusScopeId, AceType::Claim(this), false);
2488         }
2489     } else if (focusPriority == static_cast<uint32_t>(FocusPriority::PREVIOUS)) {
2490         focusPriority_ = FocusPriority::PREVIOUS;
2491         if (focusManager) {
2492             focusManager->AddScopePriorityNode(focusScopeId, AceType::Claim(this), true);
2493         }
2494     } else {
2495         if (focusScopeId_ == focusScopeId && focusPriority_ != FocusPriority::AUTO && focusManager) {
2496             focusManager->RemoveScopePriorityNode(focusScopeId, AceType::Claim(this));
2497         }
2498         focusPriority_ = FocusPriority::AUTO;
2499     }
2500     focusScopeId_ = focusScopeId;
2501 }
2502 
IsInFocusGroup()2503 bool FocusHub::IsInFocusGroup()
2504 {
2505     if (GetIsFocusGroup() && !IsNestingFocusGroup()) {
2506         return true;
2507     }
2508     auto parent = GetParentFocusHub();
2509     while (parent) {
2510         if (parent->GetIsFocusGroup() && !parent->IsNestingFocusGroup()) {
2511             return true;
2512         }
2513         auto frameNode = parent->GetFrameNode();
2514         auto focusView = frameNode ? frameNode->GetPattern<FocusView>() : nullptr;
2515         if (focusView) {
2516             return false;
2517         }
2518         parent = parent->GetParentFocusHub();
2519     }
2520     return false;
2521 }
2522 
SetLastWeakFocusNodeWholeScope(const std::string & focusScopeId)2523 void FocusHub::SetLastWeakFocusNodeWholeScope(const std::string& focusScopeId)
2524 {
2525     RefPtr<FocusHub> thisNode = AceType::Claim(this);
2526     auto parent = GetParentFocusHub();
2527     while (parent) {
2528         parent->SetLastWeakFocusNode(AceType::WeakClaim(AceType::RawPtr(thisNode)));
2529         if (parent->GetIsFocusScope() && (parent->GetFocusScopeId() == focusScopeId)) {
2530             return;
2531         }
2532         thisNode = parent;
2533         parent = parent->GetParentFocusHub();
2534     }
2535 }
2536 
IsFocusAbleChildOf(const RefPtr<FocusHub> & parentFocusHub)2537 bool FocusHub::IsFocusAbleChildOf(const RefPtr<FocusHub>& parentFocusHub)
2538 {
2539     auto parent = GetParentFocusHub();
2540     while (parent) {
2541         if (parent == parentFocusHub) {
2542             if (!IsFocusableWholePath()) {
2543                 return false;
2544             }
2545             return true;
2546         }
2547         parent = parent->GetParentFocusHub();
2548     }
2549     return false;
2550 }
2551 
GetChildPriorfocusNode(const std::string & focusScopeId)2552 WeakPtr<FocusHub> FocusHub::GetChildPriorfocusNode(const std::string& focusScopeId)
2553 {
2554     if (focusScopeId.empty()) {
2555         return nullptr;
2556     }
2557 
2558     auto focusManager = GetFocusManager();
2559     if (!focusManager) {
2560         return nullptr;
2561     }
2562     RefPtr<FocusHub> thisNode = AceType::Claim(this);
2563     auto optionalList = focusManager->GetFocusScopePriorityList(focusScopeId);
2564     if (!optionalList.has_value()) {
2565         return nullptr;
2566     }
2567     auto focusScopePriorityList = optionalList.value();
2568     for (const auto& childWeak : (*focusScopePriorityList)) {
2569         auto child = childWeak.Upgrade();
2570         if (!child) {
2571             continue;
2572         }
2573         if (child->IsFocusAbleChildOf(thisNode)) {
2574             return childWeak;
2575         }
2576     }
2577     return nullptr;
2578 }
2579 
SetLastWeakFocusNodeToPreviousNode()2580 bool FocusHub::SetLastWeakFocusNodeToPreviousNode()
2581 {
2582     if (focusType_ != FocusType::SCOPE || focusScopeId_.empty() || !isFocusScope_) {
2583         return false;
2584     }
2585     auto newFocusNodeWeak = GetChildPriorfocusNode(focusScopeId_);
2586     auto newFocusNode = newFocusNodeWeak.Upgrade();
2587     if (!newFocusNode) {
2588         return false;
2589     }
2590     if (newFocusNode->GetFocusPriority() == FocusPriority::PREVIOUS) {
2591         newFocusNode->SetLastWeakFocusNodeWholeScope(focusScopeId_);
2592         return true;
2593     }
2594     return false;
2595 }
2596 
SetLastWeakFocusToPreviousInFocusView()2597 void FocusHub::SetLastWeakFocusToPreviousInFocusView()
2598 {
2599     if (SetLastWeakFocusNodeToPreviousNode()) {
2600         return;
2601     }
2602     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
2603     while (lastFocusNode) {
2604         if (lastFocusNode->SetLastWeakFocusNodeToPreviousNode()) {
2605             return;
2606         }
2607         auto newLastWeak = lastFocusNode->GetLastWeakFocusNode();
2608         lastFocusNode = newLastWeak.Upgrade();
2609     }
2610     return;
2611 }
2612 
AcceptFocusOfPriorityChild()2613 bool FocusHub::AcceptFocusOfPriorityChild()
2614 {
2615     if (focusType_ != FocusType::SCOPE || focusScopeId_.empty() || !isFocusScope_) {
2616         return false;
2617     }
2618 
2619     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
2620     if (!lastFocusNode) {
2621         auto newFocusNodeWeak = GetChildPriorfocusNode(focusScopeId_);
2622         auto newFocusNode = newFocusNodeWeak.Upgrade();
2623         if (!newFocusNode) {
2624             return false;
2625         }
2626         newFocusNode->SetLastWeakFocusNodeWholeScope(focusScopeId_);
2627         return true;
2628     } else {
2629         if (GetIsFocusGroup() && !IsNestingFocusGroup()) {
2630             SetLastWeakFocusNodeToPreviousNode();
2631             return true;
2632         }
2633     }
2634     return false;
2635 }
2636 
RequestFocusByPriorityInScope()2637 bool FocusHub::RequestFocusByPriorityInScope()
2638 {
2639     if (focusScopeId_.empty() || !isFocusScope_) {
2640         return false;
2641     }
2642     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
2643     if (!lastFocusNode) {
2644         auto newFocusNodeWeak = GetChildPriorfocusNode(focusScopeId_);
2645         auto newFocusNode = newFocusNodeWeak.Upgrade();
2646         if (!newFocusNode) {
2647             return false;
2648         }
2649         newFocusNode->SetLastWeakFocusNodeWholeScope(focusScopeId_);
2650         lastFocusNode = lastWeakFocusNode_.Upgrade();
2651         if (lastFocusNode && lastFocusNode->RequestFocusImmediatelyInner()) {
2652             return true;
2653         }
2654         return false;
2655     }
2656     if (GetIsFocusGroup() && !IsNestingFocusGroup()) {
2657         SetLastWeakFocusNodeToPreviousNode();
2658         lastFocusNode = lastWeakFocusNode_.Upgrade();
2659         if (lastFocusNode && lastFocusNode->RequestFocusImmediatelyInner()) {
2660             return true;
2661         }
2662     }
2663     return false;
2664 }
2665 
IsNestingFocusGroup()2666 bool FocusHub::IsNestingFocusGroup()
2667 {
2668     if (!GetIsFocusGroup()) {
2669         return false;
2670     }
2671     auto parent = GetParentFocusHub();
2672     while (parent) {
2673         if (parent->GetIsFocusGroup()) {
2674             return true;
2675         }
2676         parent = parent->GetParentFocusHub();
2677     }
2678     return false;
2679 }
2680 
ToJsonValue(const RefPtr<FocusHub> & hub,std::unique_ptr<JsonValue> & json,const InspectorFilter & filter)2681 void FocusHub::ToJsonValue(
2682     const RefPtr<FocusHub>& hub, std::unique_ptr<JsonValue>& json, const InspectorFilter& filter)
2683 {
2684     bool focusable = false;
2685     bool focused = false;
2686     if (hub) {
2687         focusable = hub->IsFocusable();
2688         focused = hub->IsCurrentFocus();
2689     }
2690     if (filter.CheckFixedAttr(FIXED_ATTR_FOCUSABLE)) {
2691         json->Put("focusable", focusable);
2692         json->Put("focused", focused);
2693     }
2694     if (filter.IsFastFilter()) {
2695         return;
2696     }
2697 
2698     bool enabled = true;
2699     bool defaultFocus = false;
2700     bool groupDefaultFocus = false;
2701     bool focusOnTouch = false;
2702     int32_t tabIndex = 0;
2703     std::unique_ptr<JsonValue> focusBox = nullptr;
2704     bool tabStop = false;
2705     if (hub) {
2706         enabled = hub->IsEnabled();
2707         defaultFocus = hub->IsDefaultFocus();
2708         groupDefaultFocus = hub->IsDefaultGroupFocus();
2709         focusOnTouch = hub->IsFocusOnTouch().value_or(false);
2710         tabIndex = hub->GetTabIndex();
2711         focusBox = FocusBox::ToJsonValue(hub->box_);
2712         tabStop = hub->IsTabStop();
2713     }
2714     json->PutExtAttr("enabled", enabled, filter);
2715     json->PutExtAttr("defaultFocus", defaultFocus, filter);
2716     json->PutExtAttr("groupDefaultFocus", groupDefaultFocus, filter);
2717     json->PutExtAttr("focusOnTouch", focusOnTouch, filter);
2718     json->PutExtAttr("tabIndex", tabIndex, filter);
2719     json->PutExtAttr("focusBox", focusBox, filter);
2720     json->PutExtAttr("tabStop", tabStop, filter);
2721 }
2722 
DumpFocusUieInJson(std::unique_ptr<JsonValue> & json)2723 void FocusHub::DumpFocusUieInJson(std::unique_ptr<JsonValue>& json)
2724 {
2725     auto frameNode = GetFrameNode();
2726     CHECK_NULL_VOID(frameNode);
2727     auto pattern = frameNode->GetPattern();
2728     if (pattern && frameNode->GetTag() == V2::UI_EXTENSION_COMPONENT_TAG) {
2729         pattern->DumpInfo(json);
2730     }
2731 }
2732 } // namespace OHOS::Ace::NG
2733