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