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