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