• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 
20 #include "base/geometry/ng/offset_t.h"
21 #include "base/geometry/ng/rect_t.h"
22 #include "base/log/dump_log.h"
23 #include "base/utils/utils.h"
24 #include "core/common/ace_application_info.h"
25 #include "core/components/theme/app_theme.h"
26 #include "core/components_ng/base/frame_node.h"
27 #include "core/components_ng/base/geometry_node.h"
28 #include "core/components_ng/event/gesture_event_hub.h"
29 #include "core/event/ace_event_handler.h"
30 #include "core/pipeline_ng/pipeline_context.h"
31 
32 namespace OHOS::Ace::NG {
33 
GetFrameNode() const34 RefPtr<FrameNode> FocusHub::GetFrameNode() const
35 {
36     auto eventHub = eventHub_.Upgrade();
37     return eventHub ? eventHub->GetFrameNode() : nullptr;
38 }
39 
GetGeometryNode() const40 RefPtr<GeometryNode> FocusHub::GetGeometryNode() const
41 {
42     auto frameNode = GetFrameNode();
43     return frameNode ? frameNode->GetGeometryNode() : nullptr;
44 }
45 
GetInspectorKey() const46 std::optional<std::string> FocusHub::GetInspectorKey() const
47 {
48     auto frameNode = GetFrameNode();
49     CHECK_NULL_RETURN_NOLOG(frameNode, std::nullopt);
50     return frameNode->GetInspectorId();
51 }
52 
GetParentFocusHub() const53 RefPtr<FocusHub> FocusHub::GetParentFocusHub() const
54 {
55     auto frameNode = GetFrameNode();
56     CHECK_NULL_RETURN_NOLOG(frameNode, nullptr);
57     auto parentNode = frameNode->GetFocusParent();
58     return parentNode ? parentNode->GetFocusHub() : nullptr;
59 }
60 
GetFrameName() const61 std::string FocusHub::GetFrameName() const
62 {
63     auto frameNode = GetFrameNode();
64     return frameNode ? frameNode->GetTag() : "NULL";
65 }
66 
GetFrameId() const67 int32_t FocusHub::GetFrameId() const
68 {
69     auto frameNode = GetFrameNode();
70     return frameNode ? frameNode->GetId() : -1;
71 }
72 
FlushChildrenFocusHub(std::list<RefPtr<FocusHub>> & focusNodes)73 std::list<RefPtr<FocusHub>>::iterator FocusHub::FlushChildrenFocusHub(std::list<RefPtr<FocusHub>>& focusNodes)
74 {
75     focusNodes.clear();
76     std::list<RefPtr<FrameNode>> childrenNode;
77     auto frameNode = GetFrameNode();
78     if (frameNode) {
79         frameNode->GetFocusChildren(childrenNode);
80     }
81     for (const auto& child : childrenNode) {
82         if (child->GetFocusHub()) {
83             focusNodes.emplace_back(child->GetFocusHub());
84         }
85     }
86     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
87     if (!lastFocusNode) {
88         return focusNodes.end();
89     }
90     return std::find(focusNodes.begin(), focusNodes.end(), lastFocusNode);
91 }
92 
HandleKeyEvent(const KeyEvent & keyEvent)93 bool FocusHub::HandleKeyEvent(const KeyEvent& keyEvent)
94 {
95     if (!IsCurrentFocus()) {
96         return false;
97     }
98     return OnKeyEvent(keyEvent);
99 }
100 
DumpFocusTree(int32_t depth)101 void FocusHub::DumpFocusTree(int32_t depth)
102 {
103     if (focusType_ == FocusType::NODE) {
104         DumpFocusNodeTree(depth);
105     } else if (focusType_ == FocusType::SCOPE) {
106         DumpFocusScopeTree(depth);
107     }
108 }
109 
DumpFocusNodeTree(int32_t depth)110 void FocusHub::DumpFocusNodeTree(int32_t depth)
111 {
112     if (DumpLog::GetInstance().GetDumpFile()) {
113         std::string information = GetFrameName();
114         if (IsCurrentFocus()) {
115             information += "(Node*)";
116         } else {
117             information += "(Node)";
118         }
119         information += (" id:" + std::to_string(GetFrameId()));
120         if (!IsFocusable()) {
121             information = "(-)" + information;
122         }
123         DumpLog::GetInstance().Print(depth, information, 0);
124     }
125 }
126 
DumpFocusScopeTree(int32_t depth)127 void FocusHub::DumpFocusScopeTree(int32_t depth)
128 {
129     std::list<RefPtr<FocusHub>> focusNodes;
130     FlushChildrenFocusHub(focusNodes);
131     if (DumpLog::GetInstance().GetDumpFile()) {
132         std::string information = GetFrameName();
133         if (IsCurrentFocus()) {
134             information += "(Scope*)";
135         } else {
136             information += "(Scope)";
137         }
138         information += (" id:" + std::to_string(GetFrameId()));
139         if (!IsFocusable()) {
140             information = "(-)" + information;
141         }
142         DumpLog::GetInstance().Print(depth, information, static_cast<int32_t>(focusNodes.size()));
143     }
144 
145     for (const auto& item : focusNodes) {
146         item->DumpFocusTree(depth + 1);
147     }
148 }
149 
RequestFocusImmediately()150 bool FocusHub::RequestFocusImmediately()
151 {
152     auto context = NG::PipelineContext::GetCurrentContext();
153     if (context && context->GetIsFocusingByTab()) {
154         if (!IsFocusableByTab()) {
155             return false;
156         }
157     }
158 
159     if (IsCurrentFocus()) {
160         return true;
161     }
162 
163     if (!IsFocusable()) {
164         return false;
165     }
166 
167     currentFocus_ = true;
168     UpdateAccessibilityFocusInfo();
169 
170     if (onPreFocusCallback_) {
171         onPreFocusCallback_();
172     }
173 
174     auto parent = GetParentFocusHub();
175     if (parent) {
176         parent->SwitchFocus(AceType::Claim(this));
177     } else {
178         LOGD("Switch focus. Has no parent.");
179     }
180 
181     HandleFocus();
182     return true;
183 }
184 
UpdateAccessibilityFocusInfo()185 void FocusHub::UpdateAccessibilityFocusInfo()
186 {
187     // Need update
188 }
189 
LostFocus(BlurReason reason)190 void FocusHub::LostFocus(BlurReason reason)
191 {
192     if (IsCurrentFocus()) {
193         blurReason_ = reason;
194         currentFocus_ = false;
195         UpdateAccessibilityFocusInfo();
196         OnBlur();
197     }
198 }
199 
LostSelfFocus()200 void FocusHub::LostSelfFocus()
201 {
202     if (IsCurrentFocus()) {
203         SetFocusable(false);
204         SetFocusable(true);
205     }
206 }
207 
RemoveSelf()208 void FocusHub::RemoveSelf()
209 {
210     auto parent = GetParentFocusHub();
211     if (parent) {
212         parent->RemoveChild(AceType::Claim(this));
213     } else {
214         LostFocus(BlurReason::FRAME_DESTROY);
215     }
216 }
217 
RemoveChild(const RefPtr<FocusHub> & focusNode)218 void FocusHub::RemoveChild(const RefPtr<FocusHub>& focusNode)
219 {
220     // Not belong to this focus scope.
221     if (!focusNode || focusNode->GetParentFocusHub() != this) {
222         return;
223     }
224 
225     std::list<RefPtr<FocusHub>> focusNodes;
226     auto itLastFocusNode = FlushChildrenFocusHub(focusNodes);
227 
228     if (focusNode->IsCurrentFocus()) {
229         // Try to goto next focus, otherwise goto previous focus.
230         if (!GoToNextFocusLinear(true) && !GoToNextFocusLinear(false)) {
231             lastWeakFocusNode_ = nullptr;
232             RemoveSelf();
233         }
234         focusNode->LostFocus(BlurReason::FRAME_DESTROY);
235     } else {
236         if (itLastFocusNode != focusNodes.end() && (*itLastFocusNode) == focusNode) {
237             lastWeakFocusNode_ = nullptr;
238         }
239     }
240 
241     auto it = std::find(focusNodes.begin(), focusNodes.end(), focusNode);
242     if (it == focusNodes.end()) {
243         return;
244     }
245     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
246     if (lastFocusNode == focusNode) {
247         lastWeakFocusNode_ = nullptr;
248     }
249 }
250 
251 // Need update RebuildChild function
252 
IsFocusable()253 bool FocusHub::IsFocusable()
254 {
255     if (focusType_ == FocusType::NODE) {
256         return IsFocusableNode();
257     }
258     if (focusType_ == FocusType::SCOPE) {
259         return IsFocusableScope();
260     }
261     return false;
262 }
263 
IsFocusableScope()264 bool FocusHub::IsFocusableScope()
265 {
266     if (!IsFocusableNode()) {
267         return false;
268     }
269     std::list<RefPtr<FocusHub>> focusNodes;
270     FlushChildrenFocusHub(focusNodes);
271     // TODO: Contaner without child can be focusable
272     return std::any_of(focusNodes.begin(), focusNodes.end(),
273         [](const RefPtr<FocusHub>& focusNode) { return focusNode->IsFocusable(); });
274 }
275 
IsFocusableNode()276 bool FocusHub::IsFocusableNode()
277 {
278     return IsEnabled() && show_ && focusable_ && parentFocusable_;
279 }
280 
SetFocusable(bool focusable)281 void FocusHub::SetFocusable(bool focusable)
282 {
283     if (focusable_ == focusable) {
284         return;
285     }
286     focusable_ = focusable;
287     RefreshParentFocusable(IsFocusable());
288     RefreshFocus();
289 }
290 
IsEnabled() const291 bool FocusHub::IsEnabled() const
292 {
293     auto eventHub = eventHub_.Upgrade();
294     return eventHub ? eventHub->IsEnabled() : true;
295 }
296 
SetEnabled(bool enabled)297 void FocusHub::SetEnabled(bool enabled)
298 {
299     if (focusType_ == FocusType::NODE) {
300         SetEnabledNode(enabled);
301     } else if (focusType_ == FocusType::SCOPE) {
302         SetEnabledScope(enabled);
303     }
304 }
305 
SetEnabledNode(bool enabled)306 void FocusHub::SetEnabledNode(bool enabled)
307 {
308     if (!enabled) {
309         RefreshFocus();
310     }
311 }
312 
SetEnabledScope(bool enabled)313 void FocusHub::SetEnabledScope(bool enabled)
314 {
315     SetEnabledNode(enabled);
316     RefreshParentFocusable(IsFocusableNode());
317 }
318 
SetShow(bool show)319 void FocusHub::SetShow(bool show)
320 {
321     if (focusType_ == FocusType::NODE) {
322         SetShowNode(show);
323     } else if (focusType_ == FocusType::SCOPE) {
324         SetShowScope(show);
325     }
326 }
327 
SetShowNode(bool show)328 void FocusHub::SetShowNode(bool show)
329 {
330     show_ = show;
331     if (!show) {
332         RefreshFocus();
333     }
334 }
335 
SetShowScope(bool show)336 void FocusHub::SetShowScope(bool show)
337 {
338     SetShowNode(show);
339     RefreshParentFocusable(IsFocusableNode());
340 }
341 
SetIsFocusOnTouch(bool isFocusOnTouch)342 void FocusHub::SetIsFocusOnTouch(bool isFocusOnTouch)
343 {
344     if (!focusCallbackEvents_) {
345         focusCallbackEvents_ = MakeRefPtr<FocusCallbackEvents>();
346     }
347     if (focusCallbackEvents_->IsFocusOnTouch().has_value() &&
348         focusCallbackEvents_->IsFocusOnTouch().value() == isFocusOnTouch) {
349         return;
350     }
351     focusCallbackEvents_->SetIsFocusOnTouch(isFocusOnTouch);
352 
353     auto frameNode = GetFrameNode();
354     CHECK_NULL_VOID(frameNode);
355     auto gesture = frameNode->GetOrCreateGestureEventHub();
356     CHECK_NULL_VOID(gesture);
357 
358     if (!isFocusOnTouch && !focusOnTouchListener_) {
359         return;
360     }
361     if (!isFocusOnTouch && focusOnTouchListener_) {
362         gesture->RemoveTouchEvent(focusOnTouchListener_);
363         return;
364     }
365     if (!focusOnTouchListener_) {
366         auto touchCallback = [weak = WeakClaim(this)](const TouchEventInfo& info) {
367             auto focusHub = weak.Upgrade();
368             if (focusHub && info.GetTouches().front().GetTouchType() == TouchType::UP) {
369                 focusHub->RequestFocusImmediately();
370             }
371         };
372         focusOnTouchListener_ = MakeRefPtr<TouchEventImpl>(std::move(touchCallback));
373     }
374     gesture->AddTouchEvent(focusOnTouchListener_);
375 }
376 
RefreshFocus()377 void FocusHub::RefreshFocus()
378 {
379     if (!IsCurrentFocus()) {
380         return;
381     }
382 
383     // lost current focus and request another focus
384     auto parent = GetParentFocusHub();
385 
386     // current node is root node
387     if (!parent) {
388         LostFocus();
389         return;
390     }
391     while (!parent->IsFocusable()) {
392         // parent node is root node
393         if (!parent->GetParentFocusHub()) {
394             parent->LostFocus();
395             return;
396         }
397         parent = parent->GetParentFocusHub();
398     }
399     parent->LostFocus();
400     parent->RequestFocusImmediately();
401 }
402 
OnKeyEvent(const KeyEvent & keyEvent)403 bool FocusHub::OnKeyEvent(const KeyEvent& keyEvent)
404 {
405     if (focusType_ == FocusType::SCOPE) {
406         return OnKeyEventScope(keyEvent);
407     }
408     if (focusType_ == FocusType::NODE) {
409         return OnKeyEventNode(keyEvent);
410     }
411     LOGE("Current node focus type: %{public}d is invalid.", focusType_);
412     return false;
413 }
414 
OnKeyEventNode(const KeyEvent & keyEvent)415 bool FocusHub::OnKeyEventNode(const KeyEvent& keyEvent)
416 {
417     ACE_DCHECK(IsCurrentFocus());
418     if (keyEvent.action == KeyAction::DOWN) {
419         switch (keyEvent.code) {
420             case KeyCode::KEY_SPACE:
421                 OnClick(keyEvent);
422                 break;
423             default:
424                 LOGD("KeyCode is %{public}d. Do nothing", keyEvent.code);
425         }
426     }
427 
428     auto retInternal = false;
429     if (onKeyEventInternal_) {
430         retInternal = onKeyEventInternal_(keyEvent);
431     }
432 
433     auto info = KeyEventInfo(keyEvent);
434     auto onKeyEventCallback = GetOnKeyCallback();
435     if (!onKeyEventCallback) {
436         return retInternal;
437     }
438     LOGD("FocusHub::OnKeyEvent: Do key callback on %{public}s/%{public}d with key event{ Code(%{public}d), "
439          "Action(%{public}d), "
440          "SourceType(%{public}d), DeviceId(%{public}" PRId64 ") }. Return: %{public}d",
441         GetFrameName().c_str(), GetFrameId(), info.GetKeyCode(), info.GetKeyType(), info.GetSourceDevice(),
442         info.GetDeviceId(), info.IsStopPropagation());
443     onKeyEventCallback(info);
444     auto retCallback = info.IsStopPropagation();
445     return retInternal || retCallback;
446 }
447 
OnKeyEventScope(const KeyEvent & keyEvent)448 bool FocusHub::OnKeyEventScope(const KeyEvent& keyEvent)
449 {
450     ACE_DCHECK(IsCurrentFocus());
451     std::list<RefPtr<FocusHub>> focusNodes;
452     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
453     if (lastFocusNode && lastFocusNode->HandleKeyEvent(keyEvent)) {
454         return true;
455     }
456 
457     if (OnKeyEventNode(keyEvent)) {
458         return true;
459     }
460 
461     if (keyEvent.action != KeyAction::DOWN) {
462         return false;
463     }
464 
465     if (!CalculatePosition()) {
466         return false;
467     }
468 
469     switch (keyEvent.code) {
470         case KeyCode::TV_CONTROL_UP:
471             LOGI("Node: %{public}s/%{public}d request next focus by Key-'UP'", GetFrameName().c_str(), GetFrameId());
472             return RequestNextFocus(FocusStep::UP, GetRect());
473         case KeyCode::TV_CONTROL_DOWN:
474             LOGI("Node: %{public}s/%{public}d request next focus by Key-'DOWN'", GetFrameName().c_str(), GetFrameId());
475             return RequestNextFocus(FocusStep::DOWN, GetRect());
476         case KeyCode::TV_CONTROL_LEFT:
477             LOGI("Node: %{public}s/%{public}d request next focus by Key-'LEFT'", GetFrameName().c_str(), GetFrameId());
478             return RequestNextFocus(FocusStep::LEFT, GetRect());
479         case KeyCode::TV_CONTROL_RIGHT:
480             LOGI("Node: %{public}s/%{public}d request next focus by Key-'RIGHT'", GetFrameName().c_str(), GetFrameId());
481             return RequestNextFocus(FocusStep::RIGHT, GetRect());
482         case KeyCode::KEY_TAB: {
483             auto context = NG::PipelineContext::GetCurrentContext();
484             bool ret = false;
485             if (keyEvent.pressedCodes.size() == 1) {
486                 LOGI("Node: %{public}s/%{public}d request next focus by Key-'TAB'", GetFrameName().c_str(),
487                     GetFrameId());
488                 context->SetIsFocusingByTab(true);
489                 ret = RequestNextFocus(FocusStep::RIGHT, GetRect()) || RequestNextFocus(FocusStep::DOWN, GetRect());
490                 context->SetIsFocusingByTab(false);
491             } else if (keyEvent.IsShiftWith(KeyCode::KEY_TAB)) {
492                 LOGI("Node: %{public}s/%{public}d request next focus by Key-'SHIFT-TAB'", GetFrameName().c_str(),
493                     GetFrameId());
494                 context->SetIsFocusingByTab(true);
495                 ret = RequestNextFocus(FocusStep::LEFT, GetRect()) || RequestNextFocus(FocusStep::UP, GetRect());
496                 context->SetIsFocusingByTab(false);
497             }
498             return ret;
499         }
500         case KeyCode::KEY_MOVE_HOME:
501             LOGI("Node: %{public}s/%{public}d request next focus by Key-'HOME'", GetFrameName().c_str(), GetFrameId());
502             return RequestNextFocus(FocusStep::LEFT_END, GetRect()) || RequestNextFocus(FocusStep::UP_END, GetRect());
503         case KeyCode::KEY_MOVE_END:
504             LOGI("Node: %{public}s/%{public}d request next focus by Key-'END'", GetFrameName().c_str(), GetFrameId());
505             return RequestNextFocus(FocusStep::RIGHT_END, GetRect()) ||
506                    RequestNextFocus(FocusStep::DOWN_END, GetRect());
507         default:
508             return false;
509     }
510 }
511 
RequestFocus() const512 void FocusHub::RequestFocus() const
513 {
514     if (IsCurrentFocus()) {
515         return;
516     }
517     auto context = NG::PipelineContext::GetCurrentContext();
518     CHECK_NULL_VOID(context);
519     context->AddDirtyFocus(GetFrameNode());
520 }
521 
RequestNextFocus(FocusStep moveStep,const RectF & rect)522 bool FocusHub::RequestNextFocus(FocusStep moveStep, const RectF& rect)
523 {
524     bool vertical = IsFocusStepVertical(moveStep);
525     bool reverse = !IsFocusStepForward(moveStep);
526     if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
527         reverse = !reverse;
528     }
529     SetScopeFocusAlgorithm();
530     if (!focusAlgorithm_.getNextFocusNode) {
531         if (focusAlgorithm_.isVertical != vertical) {
532             return false;
533         }
534         return GoToNextFocusLinear(reverse, rect);
535     }
536     WeakPtr<FocusHub> nextFocusHubWeak;
537     focusAlgorithm_.getNextFocusNode(moveStep, lastWeakFocusNode_, nextFocusHubWeak);
538     auto nextFocusHub = nextFocusHubWeak.Upgrade();
539     if (!nextFocusHub) {
540         LOGE("Can't find next focus hub with focus algorithm.");
541         return false;
542     }
543     return nextFocusHub->RequestFocusImmediately();
544 }
545 
RefreshParentFocusable(bool focusable)546 void FocusHub::RefreshParentFocusable(bool focusable)
547 {
548     if (focusType_ != FocusType::SCOPE) {
549         return;
550     }
551     std::list<RefPtr<FocusHub>> focusNodes;
552     FlushChildrenFocusHub(focusNodes);
553     for (auto& item : focusNodes) {
554         if (focusable != item->IsParentFocusable()) {
555             item->SetParentFocusable(focusable);
556             item->RefreshParentFocusable(item->IsFocusableNode());
557         }
558     }
559 }
560 
OnClick(const KeyEvent & event)561 void FocusHub::OnClick(const KeyEvent& event)
562 {
563     auto onClickCallback = GetOnClickCallback();
564     if (onClickCallback) {
565         auto info = GestureEvent();
566         info.SetTimeStamp(event.timeStamp);
567         auto rect = GetGeometryNode()->GetFrameRect();
568         info.SetGlobalLocation(Offset((rect.Left() + rect.Right()) / 2, (rect.Top() + rect.Bottom()) / 2));
569         info.SetLocalLocation(Offset((rect.Right() - rect.Left()) / 2, (rect.Bottom() - rect.Top()) / 2));
570         info.SetSourceDevice(event.sourceType);
571         info.SetDeviceId(event.deviceId);
572         LOGD("FocusHub::OnClick: Do click callback on %{public}s/%{public}d with key event{ "
573              "Global(%{public}f,%{public}f), Local(%{public}f,%{public}f), SourceType(%{public}d), "
574              "DeviceId(%{public}" PRId64 ") }",
575             GetFrameName().c_str(), GetFrameId(), info.GetGlobalLocation().GetX(), info.GetGlobalLocation().GetY(),
576             info.GetLocalLocation().GetX(), info.GetLocalLocation().GetY(), info.GetSourceDevice(), info.GetDeviceId());
577         onClickCallback(info);
578     }
579 }
580 
SwitchFocus(const RefPtr<FocusHub> & focusNode)581 void FocusHub::SwitchFocus(const RefPtr<FocusHub>& focusNode)
582 {
583     if (focusType_ != FocusType::SCOPE) {
584         LOGE("SwitchFocus: parent focus node is not a scope!");
585         return;
586     }
587     std::list<RefPtr<FocusHub>> focusNodes;
588     FlushChildrenFocusHub(focusNodes);
589 
590     auto it = std::find(focusNodes.begin(), focusNodes.end(), focusNode);
591     if (it == focusNodes.end()) {
592         LOGE("SwitchFocus: Can't find node: %{public}s/%{public}d in parent: %{public}s/%{public}d 's children",
593             focusNode->GetFrameName().c_str(), focusNode->GetFrameId(), GetFrameName().c_str(), GetFrameId());
594     }
595 
596     auto focusNodeNeedBlur = lastWeakFocusNode_.Upgrade();
597     lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(focusNode));
598 
599     if (focusNodeNeedBlur) {
600         LOGD("Switch focus frome %{public}s/%{public}d to %{public}s/%{public}d",
601             focusNodeNeedBlur->GetFrameName().c_str(), focusNodeNeedBlur->GetFrameId(),
602             focusNode->GetFrameName().c_str(), focusNode->GetFrameId());
603     } else {
604         LOGD("Switch focus frome NULL/NULL to %{public}s/%{public}d", focusNode->GetFrameName().c_str(),
605             focusNode->GetFrameId());
606     }
607     if (IsCurrentFocus()) {
608         if (focusNodeNeedBlur && focusNodeNeedBlur != focusNode) {
609             focusNodeNeedBlur->LostFocus();
610         }
611     } else {
612         RequestFocusImmediately();
613     }
614 }
615 
GoToNextFocusLinear(bool reverse,const RectF & rect)616 bool FocusHub::GoToNextFocusLinear(bool reverse, const RectF& rect)
617 {
618     std::list<RefPtr<FocusHub>> focusNodes;
619     auto itNewFocusNode = FlushChildrenFocusHub(focusNodes);
620     if (focusNodes.empty()) {
621         LOGW("FocusNode: %{public}s/%{public}d has no next child focus node to go.", GetFrameName().c_str(),
622             GetFrameId());
623         return false;
624     }
625     if (itNewFocusNode == focusNodes.end()) {
626         itNewFocusNode = focusNodes.begin();
627     }
628     if (reverse) {
629         if (itNewFocusNode == focusNodes.begin()) {
630             itNewFocusNode = focusNodes.end();
631             return false;
632         }
633         --itNewFocusNode;
634 
635         while (itNewFocusNode != focusNodes.begin()) {
636             if (TryRequestFocus(*itNewFocusNode, rect)) {
637                 return true;
638             }
639             --itNewFocusNode;
640         }
641         if (itNewFocusNode == focusNodes.begin()) {
642             if (TryRequestFocus(*itNewFocusNode, rect)) {
643                 return true;
644             }
645         }
646     } else {
647         if (itNewFocusNode != focusNodes.end()) {
648             ++itNewFocusNode;
649         }
650         while (itNewFocusNode != focusNodes.end()) {
651             if (TryRequestFocus(*itNewFocusNode, rect)) {
652                 return true;
653             }
654             ++itNewFocusNode;
655         }
656     }
657 
658     return false;
659 }
660 
TryRequestFocus(const RefPtr<FocusHub> & focusNode,const RectF & rect)661 bool FocusHub::TryRequestFocus(const RefPtr<FocusHub>& focusNode, const RectF& rect)
662 {
663     if (focusNode->AcceptFocusOfLastFocus()) {
664         return focusNode->RequestFocusImmediately();
665     }
666     if (rect.IsValid()) {
667         RectF childRect;
668         if (!CalculateRect(focusNode, childRect) ||
669             !focusNode->AcceptFocusByRectOfLastFocus(rect - childRect.GetOffset())) {
670             return false;
671         }
672     }
673     return focusNode->RequestFocusImmediately();
674 }
675 
CalculatePosition()676 bool FocusHub::CalculatePosition()
677 {
678     std::list<RefPtr<FocusHub>> focusNodes;
679     FlushChildrenFocusHub(focusNodes);
680     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
681     CHECK_NULL_RETURN(lastFocusNode, false);
682 
683     RectF childRect;
684     if (!CalculateRect(lastFocusNode, childRect)) {
685         return false;
686     }
687 
688     if (lastFocusNode->IsChild()) {
689         auto lastFocusGeometryNode = lastFocusNode->GetGeometryNode();
690         CHECK_NULL_RETURN(lastFocusGeometryNode, false);
691         RectF rect(childRect.GetOffset(), lastFocusGeometryNode->GetFrameSize());
692         lastFocusNode->SetRect(rect);
693         SetRect(rect);
694     } else {
695         SetRect(lastFocusNode->GetRect() + childRect.GetOffset());
696     }
697 
698     return true;
699 }
700 
SetScopeFocusAlgorithm()701 void FocusHub::SetScopeFocusAlgorithm()
702 {
703     auto frame = GetFrameNode();
704     CHECK_NULL_VOID(frame);
705     auto pattern = frame->GetPattern();
706     CHECK_NULL_VOID(pattern);
707     focusAlgorithm_ = pattern->GetScopeFocusAlgorithm();
708 }
709 
OnFocus()710 void FocusHub::OnFocus()
711 {
712     if (focusType_ == FocusType::NODE) {
713         OnFocusNode();
714     } else if (focusType_ == FocusType::SCOPE) {
715         OnFocusScope();
716     } else {
717         LOGE("Current node focus type: %{public}d is invalid.", focusType_);
718     }
719 }
720 
OnBlur()721 void FocusHub::OnBlur()
722 {
723     if (focusType_ == FocusType::NODE) {
724         OnBlurNode();
725     } else if (focusType_ == FocusType::SCOPE) {
726         OnBlurScope();
727     } else {
728         LOGE("Current node focus type: %{public}d is invalid.", focusType_);
729     }
730 }
731 
OnFocusNode()732 void FocusHub::OnFocusNode()
733 {
734     LOGI("FocusHub: Node(%{public}s/%{public}d) on focus", GetFrameName().c_str(), GetFrameId());
735     if (onFocusInternal_) {
736         onFocusInternal_();
737     }
738     auto onFocusCallback = GetOnFocusCallback();
739     if (onFocusCallback) {
740         onFocusCallback();
741     }
742     // check focus state style.
743     CheckFocusStateStyle(true);
744     PaintFocusState();
745 }
746 
OnBlurNode()747 void FocusHub::OnBlurNode()
748 {
749     LOGI("FocusHub: Node(%{public}s/%{public}d) on blur", GetFrameName().c_str(), GetFrameId());
750     if (onBlurInternal_) {
751         onBlurInternal_();
752     }
753     if (onBlurReasonInternal_) {
754         LOGI("FocusHub: Node(%{public}s/%{public}d) 's blur reason is %{public}d", GetFrameName().c_str(), GetFrameId(),
755             blurReason_);
756         onBlurReasonInternal_(blurReason_);
757     }
758     auto onBlurCallback = GetOnBlurCallback();
759     if (onBlurCallback) {
760         onBlurCallback();
761     }
762     // check focus state style.
763     CheckFocusStateStyle(false);
764     if (blurReason_ != BlurReason::FRAME_DESTROY) {
765         ClearFocusState();
766     }
767 }
768 
CheckFocusStateStyle(bool onFocus)769 void FocusHub::CheckFocusStateStyle(bool onFocus)
770 {
771     auto eventHub = eventHub_.Upgrade();
772     CHECK_NULL_VOID(eventHub);
773     if (onFocus) {
774         eventHub->UpdateCurrentUIState(UI_STATE_FOCUSED);
775     } else {
776         eventHub->ResetCurrentUIState(UI_STATE_FOCUSED);
777     }
778 }
779 
OnFocusScope()780 void FocusHub::OnFocusScope()
781 {
782     std::list<RefPtr<FocusHub>> focusNodes;
783     auto itLastFocusNode = FlushChildrenFocusHub(focusNodes);
784     if (focusNodes.empty()) {
785         LOGE("OnFocusScope focus nodes is empty. No child will be focused.");
786         return;
787     }
788 
789     auto itFocusNode = itLastFocusNode;
790     do {
791         if (itLastFocusNode == focusNodes.end()) {
792             itLastFocusNode = focusNodes.begin();
793             lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*itLastFocusNode));
794             if (itLastFocusNode == itFocusNode) {
795                 break;
796             }
797         }
798         lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*itLastFocusNode));
799         if ((*itLastFocusNode)->RequestFocusImmediately()) {
800             OnFocusNode();
801             return;
802         }
803     } while ((++itLastFocusNode) != itFocusNode);
804 
805     // Not found any focusable node, clear focus.
806     itLastFocusNode = focusNodes.end();
807     lastWeakFocusNode_ = nullptr;
808 }
809 
OnBlurScope()810 void FocusHub::OnBlurScope()
811 {
812     std::list<RefPtr<FocusHub>> focusNodes;
813     FlushChildrenFocusHub(focusNodes);
814     OnBlurNode();
815     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
816     if (lastFocusNode) {
817         lastFocusNode->LostFocus(blurReason_);
818     }
819 }
820 
PaintFocusState()821 void FocusHub::PaintFocusState()
822 {
823     auto context = PipelineContext::GetCurrentContext();
824     CHECK_NULL_VOID(context);
825     auto frameNode = GetFrameNode();
826     CHECK_NULL_VOID(frameNode);
827     auto renderContext = frameNode->GetRenderContext();
828     CHECK_NULL_VOID(renderContext);
829     if (focusStyleType_ == FocusStyleType::NONE || !context->GetIsNeedShowFocus()) {
830         return;
831     }
832 
833     if (focusStyleType_ == FocusStyleType::CUSTOM_REGION) {
834         CHECK_NULL_VOID(getInnerFocusRectFunc_);
835         RoundRect focusRectInner;
836         getInnerFocusRectFunc_(focusRectInner);
837         PaintInnerFocusState(focusRectInner);
838         return;
839     }
840 
841     auto appTheme = context->GetTheme<AppTheme>();
842     CHECK_NULL_VOID(appTheme);
843     Color paintColor;
844     if (HasPaintColor()) {
845         paintColor = GetPaintColor();
846     } else {
847         paintColor = appTheme->GetFocusColor();
848     }
849     Dimension paintWidth;
850     if (HasPaintWidth()) {
851         paintWidth = GetPaintWidth();
852     } else {
853         paintWidth = appTheme->GetFocusWidthVp();
854     }
855 
856     if (focusStyleType_ == FocusStyleType::CUSTOM_BORDER) {
857         if (!HasPaintRect()) {
858             LOGE("PaintFocusState: frame rect has no value while focus style is CUSTOMIZE");
859             return;
860         }
861         renderContext->PaintFocusState(GetPaintRect(), paintColor, paintWidth);
862         return;
863     }
864 
865     Dimension focusPaddingVp = Dimension(0.0, DimensionUnit::VP);
866     if (HasFocusPadding()) {
867         focusPaddingVp = GetFocusPadding();
868     } else {
869         if (focusStyleType_ == FocusStyleType::INNER_BORDER) {
870             focusPaddingVp = -appTheme->GetFocusWidthVp();
871         } else if (focusStyleType_ == FocusStyleType::OUTER_BORDER) {
872             focusPaddingVp = appTheme->GetFocusOutPaddingVp();
873         }
874     }
875     if (HasPaintRect()) {
876         renderContext->PaintFocusState(GetPaintRect(), focusPaddingVp, paintColor, paintWidth);
877     } else {
878         renderContext->PaintFocusState(focusPaddingVp, paintColor, paintWidth);
879     }
880 }
881 
PaintAllFocusState()882 void FocusHub::PaintAllFocusState()
883 {
884     PaintFocusState();
885     std::list<RefPtr<FocusHub>> focusNodes;
886     FlushChildrenFocusHub(focusNodes);
887     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
888     if (lastFocusNode) {
889         lastFocusNode->PaintAllFocusState();
890     }
891 }
892 
PaintInnerFocusState(const RoundRect & paintRect)893 void FocusHub::PaintInnerFocusState(const RoundRect& paintRect)
894 {
895     auto context = PipelineContext::GetCurrentContext();
896     CHECK_NULL_VOID(context);
897     auto frameNode = GetFrameNode();
898     CHECK_NULL_VOID(frameNode);
899     auto renderContext = frameNode->GetRenderContext();
900     CHECK_NULL_VOID(renderContext);
901     if (!context->GetIsNeedShowFocus()) {
902         return;
903     }
904     auto appTheme = context->GetTheme<AppTheme>();
905     CHECK_NULL_VOID(appTheme);
906     Color paintColor;
907     if (HasPaintColor()) {
908         paintColor = GetPaintColor();
909     } else {
910         paintColor = appTheme->GetFocusColor();
911     }
912     Dimension paintWidth;
913     if (HasPaintWidth()) {
914         paintWidth = GetPaintWidth();
915     } else {
916         paintWidth = appTheme->GetFocusWidthVp();
917     }
918     renderContext->ClearFocusState();
919     renderContext->PaintFocusState(paintRect, paintColor, paintWidth);
920 }
921 
ClearFocusState()922 void FocusHub::ClearFocusState()
923 {
924     if (focusStyleType_ != FocusStyleType::NONE) {
925         auto frameNode = GetFrameNode();
926         CHECK_NULL_VOID(frameNode);
927         auto renderContext = frameNode->GetRenderContext();
928         CHECK_NULL_VOID(renderContext);
929         renderContext->ClearFocusState();
930     }
931 }
932 
ClearAllFocusState()933 void FocusHub::ClearAllFocusState()
934 {
935     ClearFocusState();
936     std::list<RefPtr<FocusHub>> focusNodes;
937     FlushChildrenFocusHub(focusNodes);
938     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
939     if (lastFocusNode) {
940         lastFocusNode->ClearAllFocusState();
941     }
942 }
943 
AcceptFocusOfLastFocus()944 bool FocusHub::AcceptFocusOfLastFocus()
945 {
946     if (focusType_ == FocusType::SCOPE) {
947         auto lastFocusNode = lastWeakFocusNode_.Upgrade();
948         return lastFocusNode ? lastFocusNode->AcceptFocusOfLastFocus() : false;
949     }
950     if (focusType_ == FocusType::NODE) {
951         return IsFocusable();
952     }
953     return false;
954 }
955 
AcceptFocusByRectOfLastFocus(const RectF & rect)956 bool FocusHub::AcceptFocusByRectOfLastFocus(const RectF& rect)
957 {
958     if (focusType_ == FocusType::NODE) {
959         return AcceptFocusByRectOfLastFocusNode(rect);
960     }
961     if (focusType_ == FocusType::SCOPE) {
962         SetScopeFocusAlgorithm();
963         if (focusAlgorithm_.scopeType == ScopeType::FLEX) {
964             return AcceptFocusByRectOfLastFocusFlex(rect);
965         }
966         return AcceptFocusByRectOfLastFocusScope(rect);
967     }
968     return false;
969 }
970 
AcceptFocusByRectOfLastFocusNode(const RectF & rect)971 bool FocusHub::AcceptFocusByRectOfLastFocusNode(const RectF& rect)
972 {
973     return IsFocusable();
974 }
975 
AcceptFocusByRectOfLastFocusScope(const RectF & rect)976 bool FocusHub::AcceptFocusByRectOfLastFocusScope(const RectF& rect)
977 {
978     std::list<RefPtr<FocusHub>> focusNodes;
979     auto itLastFocusNode = FlushChildrenFocusHub(focusNodes);
980     if (focusNodes.empty()) {
981         return false;
982     }
983     auto itFocusNode = itLastFocusNode;
984     do {
985         if (itLastFocusNode == focusNodes.end()) {
986             itLastFocusNode = focusNodes.begin();
987             lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*itLastFocusNode));
988             if (itLastFocusNode == itFocusNode) {
989                 break;
990             }
991         }
992         RectF childRect;
993         if (!CalculateRect(*itLastFocusNode, childRect)) {
994             continue;
995         }
996 
997         if ((*itLastFocusNode)->AcceptFocusByRectOfLastFocus(rect - childRect.GetOffset())) {
998             lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*itLastFocusNode));
999             return true;
1000         }
1001     } while ((++itLastFocusNode) != itFocusNode);
1002     if (itLastFocusNode == focusNodes.end()) {
1003         lastWeakFocusNode_ = nullptr;
1004     } else {
1005         lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*itLastFocusNode));
1006     }
1007 
1008     return false;
1009 }
1010 
AcceptFocusByRectOfLastFocusFlex(const RectF & rect)1011 bool FocusHub::AcceptFocusByRectOfLastFocusFlex(const RectF& rect)
1012 {
1013     if (!rect.IsValid()) {
1014         LOGE("the rect is not valid");
1015         return false;
1016     }
1017 
1018     std::list<RefPtr<FocusHub>> focusNodes;
1019     FlushChildrenFocusHub(focusNodes);
1020     OffsetF offset;
1021     auto itNewFocusNode = focusNodes.end();
1022     double minVal = std::numeric_limits<double>::max();
1023     for (auto it = focusNodes.begin(); it != focusNodes.end(); ++it) {
1024         if (!(*it)->IsFocusable()) {
1025             continue;
1026         }
1027 
1028         RectF childRect;
1029         if (!CalculateRect(*it, childRect)) {
1030             continue;
1031         }
1032 
1033         OffsetF vec = childRect.Center() - rect.Center();
1034         double val = (vec.GetX() * vec.GetX()) + (vec.GetY() * vec.GetY());
1035         if (minVal > val) {
1036             minVal = val;
1037             itNewFocusNode = it;
1038             offset = childRect.GetOffset();
1039         }
1040     }
1041 
1042     if (itNewFocusNode != focusNodes.end() && (*itNewFocusNode)->AcceptFocusByRectOfLastFocus(rect - offset)) {
1043         lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*itNewFocusNode));
1044         return true;
1045     }
1046     return false;
1047 }
1048 
CalculateRect(const RefPtr<FocusHub> & childNode,RectF & rect) const1049 bool FocusHub::CalculateRect(const RefPtr<FocusHub>& childNode, RectF& rect) const
1050 {
1051     auto childGeometryNode = childNode->GetGeometryNode();
1052     CHECK_NULL_RETURN(childGeometryNode, false);
1053     rect = childGeometryNode->GetFrameRect();
1054     return true;
1055 }
1056 
IsFocusableByTab()1057 bool FocusHub::IsFocusableByTab()
1058 {
1059     if (focusType_ == FocusType::NODE) {
1060         return IsFocusableNodeByTab();
1061     }
1062     if (focusType_ == FocusType::SCOPE) {
1063         return IsFocusableScopeByTab();
1064     }
1065     LOGE("Current node focus type: %{public}d is invalid.", focusType_);
1066     return false;
1067 }
1068 
IsFocusableNodeByTab()1069 bool FocusHub::IsFocusableNodeByTab()
1070 {
1071     auto parent = GetParentFocusHub();
1072     CHECK_NULL_RETURN_NOLOG(parent, GetTabIndex() == 0);
1073     return (GetTabIndex() == 0) && (parent->GetTabIndex() == 0);
1074 }
1075 
IsFocusableScopeByTab()1076 bool FocusHub::IsFocusableScopeByTab()
1077 {
1078     std::list<RefPtr<FocusHub>> focusNodes;
1079     FlushChildrenFocusHub(focusNodes);
1080     if (!IsFocusableNodeByTab()) {
1081         return false;
1082     }
1083     if (focusNodes.empty()) {
1084         return true;
1085     }
1086     return std::any_of(focusNodes.begin(), focusNodes.end(),
1087         [](const RefPtr<FocusHub>& focusNode) { return focusNode->IsFocusableByTab(); });
1088 }
1089 
IsFocusableWholePath()1090 bool FocusHub::IsFocusableWholePath()
1091 {
1092     auto parent = GetParentFocusHub();
1093     while (parent) {
1094         if (!parent->IsFocusable()) {
1095             return false;
1096         }
1097         parent = parent->GetParentFocusHub();
1098     }
1099     return IsFocusable();
1100 }
1101 
CollectTabIndexNodes(TabIndexNodeList & tabIndexNodes)1102 void FocusHub::CollectTabIndexNodes(TabIndexNodeList& tabIndexNodes)
1103 {
1104     std::list<RefPtr<FocusHub>> focusNodes;
1105     FlushChildrenFocusHub(focusNodes);
1106     if (GetFocusType() == FocusType::SCOPE && IsFocusable()) {
1107         if (focusNodes.size() == 1 && focusNodes.front()->GetFocusType() != FocusType::SCOPE) {
1108             if (GetTabIndex() > 0) {
1109                 tabIndexNodes.emplace_back(GetTabIndex(), WeakClaim(this));
1110             }
1111             return;
1112         }
1113         for (auto& child : focusNodes) {
1114             child->CollectTabIndexNodes(tabIndexNodes);
1115         }
1116     }
1117     if (IsFocusable() && GetTabIndex() > 0) {
1118         tabIndexNodes.emplace_back(GetTabIndex(), WeakClaim(this));
1119     }
1120 }
1121 
GoToFocusByTabNodeIdx(TabIndexNodeList & tabIndexNodes,int32_t tabNodeIdx)1122 bool FocusHub::GoToFocusByTabNodeIdx(TabIndexNodeList& tabIndexNodes, int32_t tabNodeIdx)
1123 {
1124     auto iter = tabIndexNodes.begin();
1125     std::advance(iter, tabNodeIdx);
1126     if (iter == tabIndexNodes.end()) {
1127         LOGE("Tab index node is not found");
1128         return false;
1129     }
1130     auto nodeNeedToFocus = (*iter).second.Upgrade();
1131     if (!nodeNeedToFocus) {
1132         LOGE("Tab index node is null");
1133         return false;
1134     }
1135     LOGI("Focus on tab index node(%{public}d)", tabNodeIdx);
1136     if (nodeNeedToFocus->GetFocusType() == FocusType::SCOPE && !nodeNeedToFocus->IsDefaultGroupHasFocused()) {
1137         auto defaultFocusNode = nodeNeedToFocus->GetChildFocusNodeByType(FocusNodeType::GROUP_DEFAULT);
1138         if (defaultFocusNode) {
1139             if (!defaultFocusNode->IsFocusableWholePath()) {
1140                 LOGW("node(%{public}d) is not focusable", tabNodeIdx);
1141                 return false;
1142             }
1143             nodeNeedToFocus->SetIsDefaultGroupHasFocused(true);
1144             return defaultFocusNode->RequestFocusImmediately();
1145         }
1146     }
1147     if (!nodeNeedToFocus->IsFocusableWholePath()) {
1148         LOGW("node(%{public}d) is not focusable", tabNodeIdx);
1149         return false;
1150     }
1151     return nodeNeedToFocus->RequestFocusImmediately();
1152 }
1153 
GetChildFocusNodeByType(FocusNodeType nodeType)1154 RefPtr<FocusHub> FocusHub::GetChildFocusNodeByType(FocusNodeType nodeType)
1155 {
1156     if (nodeType == FocusNodeType::DEFAULT && IsDefaultFocus() && IsFocusable()) {
1157         return AceType::Claim(this);
1158     }
1159     if (nodeType == FocusNodeType::GROUP_DEFAULT && IsDefaultGroupFocus() && IsFocusable()) {
1160         return AceType::Claim(this);
1161     }
1162     if (focusType_ != FocusType::SCOPE) {
1163         return nullptr;
1164     }
1165     std::list<RefPtr<FocusHub>> focusNodes;
1166     FlushChildrenFocusHub(focusNodes);
1167     for (const auto& child : focusNodes) {
1168         auto findNode = child->GetChildFocusNodeByType(nodeType);
1169         if (findNode) {
1170             return findNode;
1171         }
1172     }
1173     return nullptr;
1174 }
1175 
GetChildFocusNodeById(const std::string & id)1176 RefPtr<FocusHub> FocusHub::GetChildFocusNodeById(const std::string& id)
1177 {
1178     if (id.empty()) {
1179         return nullptr;
1180     }
1181     if (GetInspectorKey().has_value() && GetInspectorKey().value() == id) {
1182         return AceType::Claim(this);
1183     }
1184     if (focusType_ == FocusType::SCOPE) {
1185         std::list<RefPtr<FocusHub>> focusNodes;
1186         FlushChildrenFocusHub(focusNodes);
1187         for (const auto& child : focusNodes) {
1188             auto findNode = child->GetChildFocusNodeById(id);
1189             if (findNode) {
1190                 return findNode;
1191             }
1192         }
1193     }
1194     return nullptr;
1195 }
1196 
RequestFocusImmediatelyById(const std::string & id)1197 bool FocusHub::RequestFocusImmediatelyById(const std::string& id)
1198 {
1199     auto focusNode = GetChildFocusNodeById(id);
1200     CHECK_NULL_RETURN(focusNode, false);
1201     if (!focusNode->IsFocusableWholePath()) {
1202         return false;
1203     }
1204     return focusNode->RequestFocusImmediately();
1205 }
1206 
GetFocusingTabNodeIdx(TabIndexNodeList & tabIndexNodes)1207 int32_t FocusHub::GetFocusingTabNodeIdx(TabIndexNodeList& tabIndexNodes)
1208 {
1209     if (tabIndexNodes.empty()) {
1210         LOGD("No tabIndex node exist in this page.");
1211         return NONE_TAB_FOCUSED_INDEX;
1212     }
1213     if (isFirstFocusInPage_) {
1214         isFirstFocusInPage_ = false;
1215         return DEFAULT_TAB_FOCUSED_INDEX;
1216     }
1217     int32_t res = NONE_TAB_FOCUSED_INDEX;
1218     int32_t i = 0;
1219     for (auto& wpNode : tabIndexNodes) {
1220         auto node = wpNode.second.Upgrade();
1221         if (node && node->IsCurrentFocus()) {
1222             res = i;
1223             break;
1224         }
1225         ++i;
1226     }
1227     return res;
1228 }
1229 
HandleFocusByTabIndex(const KeyEvent & event,const RefPtr<FocusHub> & mainFocusHub)1230 bool FocusHub::HandleFocusByTabIndex(const KeyEvent& event, const RefPtr<FocusHub>& mainFocusHub)
1231 {
1232     if (event.code != KeyCode::KEY_TAB || event.action != KeyAction::DOWN) {
1233         return false;
1234     }
1235     CHECK_NULL_RETURN(mainFocusHub, false);
1236     TabIndexNodeList tabIndexNodes;
1237     tabIndexNodes.clear();
1238     mainFocusHub->CollectTabIndexNodes(tabIndexNodes);
1239     tabIndexNodes.sort([](std::pair<int32_t, WeakPtr<FocusHub>>& a, std::pair<int32_t, WeakPtr<FocusHub>>& b) {
1240         return a.first < b.first;
1241     });
1242     int32_t curTabFocusIndex = mainFocusHub->GetFocusingTabNodeIdx(tabIndexNodes);
1243     if ((curTabFocusIndex < 0 || curTabFocusIndex >= static_cast<int32_t>(tabIndexNodes.size())) &&
1244         curTabFocusIndex != DEFAULT_TAB_FOCUSED_INDEX) {
1245         LOGI("Current focused tabIndex node: %{public}d. Use default focus system.", curTabFocusIndex);
1246         return false;
1247     }
1248     if (curTabFocusIndex == DEFAULT_TAB_FOCUSED_INDEX) {
1249         curTabFocusIndex = 0;
1250     } else {
1251         if (event.IsShiftWith(KeyCode::KEY_TAB)) {
1252             LOGI("RequestNextFocus by 'SHIFT-TAB'");
1253             --curTabFocusIndex;
1254         } else {
1255             LOGI("RequestNextFocus by 'TAB'");
1256             ++curTabFocusIndex;
1257         }
1258     }
1259     if (curTabFocusIndex < 0 || curTabFocusIndex >= static_cast<int32_t>(tabIndexNodes.size())) {
1260         LOGI("Focus from tab index node to normal node. Use default focus system.");
1261         return false;
1262     }
1263     return GoToFocusByTabNodeIdx(tabIndexNodes, curTabFocusIndex);
1264 }
1265 } // namespace OHOS::Ace::NG
1266