• 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 
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/components_v2/inspector/inspector_constants.h"
30 #include "core/event/ace_event_handler.h"
31 #include "core/pipeline_ng/pipeline_context.h"
32 
33 #ifdef WINDOW_SCENE_SUPPORTED
34 #include "core/components_ng/pattern/window_scene/helper/window_scene_helper.h"
35 #endif
36 
37 #if not defined(ACE_UNITTEST)
38 #if defined(ENABLE_STANDARD_INPUT)
39 #include "core/components_ng/pattern/text_field/on_text_changed_listener_impl.h"
40 #endif
41 #endif
42 
43 namespace OHOS::Ace::NG {
44 
GetFrameNode() const45 RefPtr<FrameNode> FocusHub::GetFrameNode() const
46 {
47     auto eventHub = eventHub_.Upgrade();
48     return eventHub ? eventHub->GetFrameNode() : nullptr;
49 }
50 
GetGeometryNode() const51 RefPtr<GeometryNode> FocusHub::GetGeometryNode() const
52 {
53     auto frameNode = GetFrameNode();
54     return frameNode ? frameNode->GetGeometryNode() : nullptr;
55 }
56 
GetInspectorKey() const57 std::optional<std::string> FocusHub::GetInspectorKey() const
58 {
59     auto frameNode = GetFrameNode();
60     CHECK_NULL_RETURN(frameNode, std::nullopt);
61     return frameNode->GetInspectorId();
62 }
63 
GetParentFocusHub() const64 RefPtr<FocusHub> FocusHub::GetParentFocusHub() const
65 {
66     auto frameNode = GetFrameNode();
67     CHECK_NULL_RETURN(frameNode, nullptr);
68     auto parentNode = frameNode->GetFocusParent();
69     return parentNode ? parentNode->GetFocusHub() : nullptr;
70 }
71 
GetRootFocusHub()72 RefPtr<FocusHub> FocusHub::GetRootFocusHub()
73 {
74     RefPtr<FocusHub> parent = AceType::Claim(this);
75     while (parent->GetParentFocusHub()) {
76         parent = parent->GetParentFocusHub();
77     }
78     return parent;
79 }
80 
GetFrameName() const81 std::string FocusHub::GetFrameName() const
82 {
83     auto frameNode = GetFrameNode();
84     return frameNode ? frameNode->GetTag() : "NULL";
85 }
86 
GetFrameId() const87 int32_t FocusHub::GetFrameId() const
88 {
89     auto frameNode = GetFrameNode();
90     return frameNode ? frameNode->GetId() : -1;
91 }
92 
FlushChildrenFocusHub(std::list<RefPtr<FocusHub>> & focusNodes)93 std::list<RefPtr<FocusHub>>::iterator FocusHub::FlushChildrenFocusHub(std::list<RefPtr<FocusHub>>& focusNodes)
94 {
95     focusNodes.clear();
96     std::list<RefPtr<FrameNode>> childrenNode;
97     auto frameNode = GetFrameNode();
98     if (frameNode) {
99         frameNode->GetFocusChildren(childrenNode);
100     }
101     for (const auto& child : childrenNode) {
102         if (child->GetFocusHub()) {
103             focusNodes.emplace_back(child->GetFocusHub());
104         }
105     }
106     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
107     if (!lastFocusNode) {
108         return focusNodes.end();
109     }
110     return std::find(focusNodes.begin(), focusNodes.end(), lastFocusNode);
111 }
112 
HandleKeyEvent(const KeyEvent & keyEvent)113 bool FocusHub::HandleKeyEvent(const KeyEvent& keyEvent)
114 {
115     if (!IsCurrentFocus()) {
116         return false;
117     }
118     bool shiftTabPressed = keyEvent.IsShiftWith(KeyCode::KEY_TAB);
119     bool leftArrowPressed = keyEvent.code == KeyCode::KEY_DPAD_LEFT;
120     hasBackwardMovement_ = keyEvent.action == KeyAction::DOWN && (shiftTabPressed || leftArrowPressed);
121 
122     bool tabOnlyPressed = (keyEvent.code == KeyCode::KEY_TAB) && (!shiftTabPressed);
123     bool rightArrowPressed = keyEvent.code == KeyCode::KEY_DPAD_RIGHT;
124     hasForwardMovement_ = keyEvent.action == KeyAction::DOWN && (tabOnlyPressed || rightArrowPressed);
125 
126     return OnKeyEvent(keyEvent);
127 }
128 
DumpFocusTree(int32_t depth)129 void FocusHub::DumpFocusTree(int32_t depth)
130 {
131     if (focusType_ == FocusType::NODE) {
132         DumpFocusNodeTree(depth);
133     } else if (focusType_ == FocusType::SCOPE) {
134         DumpFocusScopeTree(depth);
135     }
136 }
137 
DumpFocusNodeTree(int32_t depth)138 void FocusHub::DumpFocusNodeTree(int32_t depth)
139 {
140     if (DumpLog::GetInstance().GetDumpFile()) {
141         std::string information = GetFrameName();
142         if (IsCurrentFocus()) {
143             information += "(Node*)";
144         } else {
145             information += "(Node)";
146         }
147         information += (" id:" + std::to_string(GetFrameId()));
148         if (!IsFocusable()) {
149             information = "(-)" + information;
150             information += (" Enabled:" + std::to_string(IsEnabled()) + " Show:" + std::to_string(IsShow()) +
151                             " Focusable:" + std::to_string(focusable_) +
152                             " ParentFocusable:" + std::to_string(parentFocusable_));
153         }
154         DumpLog::GetInstance().Print(depth, information, 0);
155     }
156 }
157 
DumpFocusScopeTree(int32_t depth)158 void FocusHub::DumpFocusScopeTree(int32_t depth)
159 {
160     std::list<RefPtr<FocusHub>> focusNodes;
161     FlushChildrenFocusHub(focusNodes);
162     if (DumpLog::GetInstance().GetDumpFile()) {
163         std::string information = GetFrameName();
164         if (IsCurrentFocus()) {
165             information += "(Scope*)";
166         } else {
167             information += "(Scope)";
168         }
169         information += (" id:" + std::to_string(GetFrameId()));
170         if (!IsFocusable()) {
171             information = "(-)" + information;
172             if (!IsFocusableNode()) {
173                 information += (" Enabled:" + std::to_string(IsEnabled()) + " Show:" + std::to_string(IsShow()) +
174                                 " Focusable:" + std::to_string(focusable_) +
175                                 " ParentFocusable:" + std::to_string(parentFocusable_));
176             }
177         }
178         DumpLog::GetInstance().Print(depth, information, static_cast<int32_t>(focusNodes.size()));
179     }
180 
181     for (const auto& item : focusNodes) {
182         item->DumpFocusTree(depth + 1);
183     }
184 }
185 
RequestFocusImmediately(bool isJudgeRootTree)186 bool FocusHub::RequestFocusImmediately(bool isJudgeRootTree)
187 {
188     auto context = NG::PipelineContext::GetCurrentContext();
189     if (context && context->GetIsFocusingByTab()) {
190         if (!IsFocusableByTab()) {
191             return false;
192         }
193     }
194 
195     if (IsCurrentFocus()) {
196         return true;
197     }
198 
199     if (!IsFocusableWholePath()) {
200         return false;
201     }
202 
203     if (isJudgeRootTree && !IsOnRootTree()) {
204         return false;
205     }
206 
207     currentFocus_ = true;
208     UpdateAccessibilityFocusInfo();
209 
210     if (onPreFocusCallback_) {
211         onPreFocusCallback_();
212     }
213 
214     auto parent = GetParentFocusHub();
215     if (parent) {
216         auto mainView = GetCurrentMainView();
217         auto mainViewRootScope = mainView ? mainView->GetMainViewRootScope() : nullptr;
218         if (mainViewRootScope && parent == mainViewRootScope) {
219             mainView->SetIsViewRootScopeFocused(mainViewRootScope, false);
220         }
221         parent->SwitchFocus(AceType::Claim(this));
222     }
223 
224     HandleFocus();
225     return true;
226 }
227 
UpdateAccessibilityFocusInfo()228 void FocusHub::UpdateAccessibilityFocusInfo()
229 {
230     // Need update
231 }
232 
GetChildMainView()233 RefPtr<FocusHub> FocusHub::GetChildMainView()
234 {
235     std::list<RefPtr<FocusHub>> children;
236     FlushChildrenFocusHub(children);
237     RefPtr<FocusHub> curFocusMainView = nullptr;
238     RefPtr<FocusHub> focusableMainView = nullptr;
239     for (const auto& child : children) {
240         if (!child) {
241             continue;
242         }
243         auto frameName = child->GetFrameName();
244         if (frameName == V2::PAGE_ETS_TAG || frameName == V2::DIALOG_ETS_TAG || frameName == V2::MODAL_PAGE_TAG ||
245             frameName == V2::MENU_ETS_TAG || frameName == V2::SHEET_PAGE_TAG || frameName == V2::POPUP_ETS_TAG ||
246             frameName == V2::WINDOW_SCENE_ETS_TAG) {
247             if (!curFocusMainView && child->IsCurrentFocus() && child->IsFocusable()) {
248                 curFocusMainView = child;
249             }
250             if (!focusableMainView && child->IsFocusable()) {
251                 focusableMainView = child;
252             }
253         }
254     }
255     if (curFocusMainView) {
256         return curFocusMainView;
257     }
258     if (focusableMainView) {
259         return focusableMainView;
260     }
261     for (const auto& child : children) {
262         if (!child) {
263             continue;
264         }
265         auto result = child->GetChildMainView();
266         if (result) {
267             return result;
268         }
269     }
270     return nullptr;
271 }
272 
GetCurrentMainView()273 RefPtr<FocusHub> FocusHub::GetCurrentMainView()
274 {
275     auto pipeline = PipelineContext::GetCurrentContext();
276     CHECK_NULL_RETURN(pipeline, nullptr);
277     auto screenNode = pipeline->GetScreenNode();
278     if (screenNode) {
279         auto screenNodeFocusHub = screenNode->GetFocusHub();
280         CHECK_NULL_RETURN(screenNodeFocusHub, nullptr);
281         return screenNodeFocusHub->GetChildMainView();
282     }
283     auto rootNode = pipeline->GetRootElement();
284     CHECK_NULL_RETURN(rootNode, nullptr);
285     auto rootFocusHub = rootNode->GetFocusHub();
286     CHECK_NULL_RETURN(rootFocusHub, nullptr);
287     return rootFocusHub->GetChildMainView();
288 }
289 
GetMainViewRootScope()290 RefPtr<FocusHub> FocusHub::GetMainViewRootScope()
291 {
292     static const std::list<int32_t> DEEPTH_OF_MENU = { 0, 0 };
293     static const std::list<int32_t> DEEPTH_OF_DIALOG = { 0, 0 };
294     static const std::list<int32_t> DEEPTH_OF_PAGE = { 0 };
295     static const std::list<int32_t> DEEPTH_OF_POPUP = { 0, 0 };
296     static const std::list<int32_t> DEEPTH_OF_SHEET_PAGE = { 1, 0 };
297     auto frameName = GetFrameName();
298     std::list<int32_t> rootScopeDeepth;
299     if (frameName == V2::MENU_ETS_TAG) {
300         rootScopeDeepth = DEEPTH_OF_MENU;
301     } else if (frameName == V2::DIALOG_ETS_TAG) {
302         rootScopeDeepth = DEEPTH_OF_DIALOG;
303     } else if (frameName == V2::POPUP_ETS_TAG) {
304         rootScopeDeepth = DEEPTH_OF_POPUP;
305     } else if (frameName == V2::SHEET_PAGE_TAG) {
306         rootScopeDeepth = DEEPTH_OF_SHEET_PAGE;
307     } else {
308         rootScopeDeepth = DEEPTH_OF_PAGE;
309     }
310     RefPtr<FocusHub> rootScope = AceType::Claim(this);
311     for (const auto& index : rootScopeDeepth) {
312         CHECK_NULL_RETURN(rootScope, nullptr);
313         auto children = rootScope->GetChildren();
314         auto iter = children.begin();
315         std::advance(iter, index);
316         if (iter == children.end()) {
317             TAG_LOGI(AceLogTag::ACE_FOCUS, "Index: %{public}d of %{public}s/%{public}d 's children is invalid.", index,
318                 rootScope->GetFrameName().c_str(), rootScope->GetFrameId());
319             return nullptr;
320         }
321         rootScope = *iter;
322     }
323     CHECK_NULL_RETURN(rootScope, nullptr);
324     if (rootScope->GetFocusType() != FocusType::SCOPE) {
325         return rootScope->GetParentFocusHub();
326     }
327     return rootScope;
328 }
329 
LostFocusToViewRoot()330 void FocusHub::LostFocusToViewRoot()
331 {
332     auto mainView = GetCurrentMainView();
333     CHECK_NULL_VOID(mainView);
334     auto mainViewRootScope = mainView->GetMainViewRootScope();
335     CHECK_NULL_VOID(mainViewRootScope);
336     TAG_LOGD(AceLogTag::ACE_FOCUS, "Lost focus to view root: %{public}s/%{public}d",
337         mainViewRootScope->GetFrameName().c_str(), mainViewRootScope->GetFrameId());
338     if (!mainViewRootScope->IsCurrentFocus()) {
339         TAG_LOGI(AceLogTag::ACE_FOCUS, "View root: %{public}s/%{public}d is not on focusing.",
340             mainViewRootScope->GetFrameName().c_str(), mainViewRootScope->GetFrameId());
341         return;
342     }
343     mainView->SetIsViewRootScopeFocused(mainViewRootScope, true);
344     auto focusedChild = mainViewRootScope->lastWeakFocusNode_.Upgrade();
345     CHECK_NULL_VOID(focusedChild);
346     focusedChild->LostFocus();
347 }
348 
HandleFocusOnMainView()349 bool FocusHub::HandleFocusOnMainView()
350 {
351     auto viewRootScope = GetMainViewRootScope();
352     CHECK_NULL_RETURN(viewRootScope, false);
353     if (!viewRootScope->IsCurrentFocus()) {
354         TAG_LOGI(AceLogTag::ACE_FOCUS,
355             "Current view root: %{public}s/%{public}d is not on focusing. Cannot handle focus.",
356             viewRootScope->GetFrameName().c_str(), viewRootScope->GetFrameId());
357         return false;
358     }
359     if (viewRootScope->GetFocusDependence() != FocusDependence::SELF) {
360         TAG_LOGI(AceLogTag::ACE_FOCUS,
361             "Current view root: %{public}s/%{public}d is not focus depend self. Do not need handle focus.",
362             viewRootScope->GetFrameName().c_str(), viewRootScope->GetFrameId());
363         return false;
364     }
365 
366     TabIndexNodeList tabIndexNodes;
367     tabIndexNodes.clear();
368     CollectTabIndexNodes(tabIndexNodes);
369     if (tabIndexNodes.empty()) {
370         // No tabIndex node in current main view. Extend focus from viewRootScope to children.
371         SetIsDefaultHasFocused(true);
372         SetIsViewRootScopeFocused(viewRootScope, false);
373         viewRootScope->OnFocusScope(true);
374         return true;
375     }
376 
377     // First tabIndex node need get focus.
378     tabIndexNodes.sort([](std::pair<int32_t, WeakPtr<FocusHub>>& a, std::pair<int32_t, WeakPtr<FocusHub>>& b) {
379         return a.first < b.first;
380     });
381     return GoToFocusByTabNodeIdx(tabIndexNodes, 0);
382 }
383 
LostFocus(BlurReason reason)384 void FocusHub::LostFocus(BlurReason reason)
385 {
386     TAG_LOGD(AceLogTag::ACE_FOCUS, "Node %{public}s/%{public}d lost focus. Lost reason: %{public}d.",
387         GetFrameName().c_str(), GetFrameId(), reason);
388     if (IsCurrentFocus()) {
389         blurReason_ = reason;
390         currentFocus_ = false;
391         UpdateAccessibilityFocusInfo();
392         OnBlur();
393     }
394 }
395 
LostSelfFocus()396 void FocusHub::LostSelfFocus()
397 {
398     if (IsCurrentFocus()) {
399         SetFocusable(false);
400         SetFocusable(true);
401     }
402 }
403 
RemoveSelf(BlurReason reason)404 void FocusHub::RemoveSelf(BlurReason reason)
405 {
406     TAG_LOGD(AceLogTag::ACE_FOCUS, "Node %{public}s/%{public}d remove self.", GetFrameName().c_str(), GetFrameId());
407     auto pipeline = PipelineContext::GetCurrentContext();
408     auto screenNode = pipeline ? pipeline->GetScreenNode() : nullptr;
409     auto screenFocusHub = screenNode ? screenNode->GetFocusHub() : nullptr;
410     auto parent = GetParentFocusHub();
411     if (parent && parent != screenFocusHub) {
412         parent->RemoveChild(AceType::Claim(this), reason);
413     } else {
414         LostFocus(reason);
415     }
416 }
417 
RemoveChild(const RefPtr<FocusHub> & focusNode,BlurReason reason)418 void FocusHub::RemoveChild(const RefPtr<FocusHub>& focusNode, BlurReason reason)
419 {
420     // Not belong to this focus scope.
421     if (!focusNode || focusNode->GetParentFocusHub() != this) {
422         return;
423     }
424 
425     std::list<RefPtr<FocusHub>> focusNodes;
426     auto itLastFocusNode = FlushChildrenFocusHub(focusNodes);
427 
428     if (focusNode->IsCurrentFocus()) {
429         // Try to goto next focus, otherwise goto previous focus.
430         if (!GoToNextFocusLinear(FocusStep::TAB) && !GoToNextFocusLinear(FocusStep::SHIFT_TAB)) {
431             lastWeakFocusNode_ = nullptr;
432             auto mainView = GetCurrentMainView();
433             auto mainViewRootScope = mainView ? mainView->GetMainViewRootScope() : nullptr;
434             if (mainViewRootScope && mainViewRootScope == AceType::Claim(this)) {
435                 mainView->SetIsViewRootScopeFocused(mainViewRootScope, true);
436             } else {
437                 RemoveSelf(reason);
438             }
439         }
440         focusNode->LostFocus(reason);
441     } else {
442         if (itLastFocusNode != focusNodes.end() && (*itLastFocusNode) == focusNode) {
443             lastWeakFocusNode_ = nullptr;
444         }
445     }
446 
447     auto it = std::find(focusNodes.begin(), focusNodes.end(), focusNode);
448     if (it == focusNodes.end()) {
449         return;
450     }
451     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
452     if (lastFocusNode == focusNode) {
453         lastWeakFocusNode_ = nullptr;
454     }
455 }
456 
457 // Need update RebuildChild function
458 
SetParentFocusable(bool parentFocusable)459 void FocusHub::SetParentFocusable(bool parentFocusable)
460 {
461     parentFocusable_ = parentFocusable;
462 }
463 
IsFocusable()464 bool FocusHub::IsFocusable()
465 {
466     if (focusType_ == FocusType::NODE) {
467         return IsFocusableNode();
468     }
469     if (focusType_ == FocusType::SCOPE) {
470         return IsFocusableScope();
471     }
472     return false;
473 }
474 
IsFocusableScope()475 bool FocusHub::IsFocusableScope()
476 {
477     if (!IsFocusableNode()) {
478         return false;
479     }
480     if (focusDepend_ == FocusDependence::SELF || focusDepend_ == FocusDependence::AUTO) {
481         return true;
482     }
483     std::list<RefPtr<FocusHub>> focusNodes;
484     FlushChildrenFocusHub(focusNodes);
485     return std::any_of(focusNodes.begin(), focusNodes.end(),
486         [](const RefPtr<FocusHub>& focusNode) { return focusNode->IsFocusable(); });
487 }
488 
IsFocusableNode()489 bool FocusHub::IsFocusableNode()
490 {
491     return IsEnabled() && IsShow() && focusable_ && parentFocusable_;
492 }
493 
SetFocusable(bool focusable,bool isExplicit)494 void FocusHub::SetFocusable(bool focusable, bool isExplicit)
495 {
496     if (isExplicit) {
497         isFocusableExplicit_ = true;
498     } else if (isFocusableExplicit_) {
499         LOGI("Current focusHub cannot be set to focusable implicitly.");
500         return;
501     } else {
502         implicitFocusable_ = focusable;
503     }
504     if (IsImplicitFocusableScope() && focusDepend_ == FocusDependence::CHILD) {
505         focusDepend_ = FocusDependence::AUTO;
506     }
507 
508     if (focusable_ == focusable) {
509         return;
510     }
511     focusable_ = focusable;
512     if (!focusable) {
513         RemoveSelf(BlurReason::FOCUS_SWITCH);
514     }
515 }
516 
IsEnabled() const517 bool FocusHub::IsEnabled() const
518 {
519     auto eventHub = eventHub_.Upgrade();
520     return eventHub ? eventHub->IsEnabled() : true;
521 }
522 
SetEnabled(bool enabled)523 void FocusHub::SetEnabled(bool enabled)
524 {
525     if (!enabled) {
526         RemoveSelf(BlurReason::FOCUS_SWITCH);
527     }
528 }
529 
IsShow() const530 bool FocusHub::IsShow() const
531 {
532     auto frameNode = GetFrameNode();
533     CHECK_NULL_RETURN(frameNode, true);
534     bool curIsVisible = frameNode->IsVisible();
535     auto parent = frameNode->GetParent();
536     while (parent) {
537         auto parentFrame = AceType::DynamicCast<FrameNode>(parent);
538         if (parentFrame && !parentFrame->IsVisible()) {
539             curIsVisible = false;
540             break;
541         }
542         parent = parent->GetParent();
543     }
544     return curIsVisible;
545 }
546 
SetShow(bool show)547 void FocusHub::SetShow(bool show)
548 {
549     if (!show) {
550         RemoveSelf(BlurReason::FOCUS_SWITCH);
551     }
552 }
553 
IsCurrentFocusWholePath()554 bool FocusHub::IsCurrentFocusWholePath()
555 {
556     if (!currentFocus_) {
557         return false;
558     }
559     if (focusType_ == FocusType::NODE) {
560         return true;
561     }
562     if (focusType_ == FocusType::SCOPE) {
563         if (focusDepend_ == FocusDependence::SELF || focusDepend_ == FocusDependence::AUTO) {
564             return true;
565         }
566         std::list<RefPtr<FocusHub>> focusNodes;
567         auto itLastFocusNode = FlushChildrenFocusHub(focusNodes);
568         if (itLastFocusNode == focusNodes.end() || !(*itLastFocusNode)) {
569             return false;
570         }
571         return (*itLastFocusNode)->IsCurrentFocusWholePath();
572     }
573     return false;
574 }
575 
SetIsFocusOnTouch(bool isFocusOnTouch)576 void FocusHub::SetIsFocusOnTouch(bool isFocusOnTouch)
577 {
578     if (!focusCallbackEvents_) {
579         focusCallbackEvents_ = MakeRefPtr<FocusCallbackEvents>();
580     }
581     if (focusCallbackEvents_->IsFocusOnTouch().has_value() &&
582         focusCallbackEvents_->IsFocusOnTouch().value() == isFocusOnTouch) {
583         return;
584     }
585     focusCallbackEvents_->SetIsFocusOnTouch(isFocusOnTouch);
586 
587     auto frameNode = GetFrameNode();
588     CHECK_NULL_VOID(frameNode);
589     auto gesture = frameNode->GetOrCreateGestureEventHub();
590     CHECK_NULL_VOID(gesture);
591 
592     if (!isFocusOnTouch && !focusOnTouchListener_) {
593         return;
594     }
595     if (!isFocusOnTouch && focusOnTouchListener_) {
596         gesture->RemoveTouchEvent(focusOnTouchListener_);
597         return;
598     }
599     if (!focusOnTouchListener_) {
600         auto touchCallback = [weak = WeakClaim(this)](const TouchEventInfo& info) {
601             auto focusHub = weak.Upgrade();
602             if (focusHub && info.GetTouches().front().GetTouchType() == TouchType::UP) {
603                 focusHub->RequestFocusImmediately();
604             }
605         };
606         focusOnTouchListener_ = MakeRefPtr<TouchEventImpl>(std::move(touchCallback));
607     }
608     gesture->AddTouchEvent(focusOnTouchListener_);
609 }
610 
SetIsDefaultFocus(bool isDefaultFocus)611 void FocusHub::SetIsDefaultFocus(bool isDefaultFocus)
612 {
613     if (!focusCallbackEvents_) {
614         focusCallbackEvents_ = MakeRefPtr<FocusCallbackEvents>();
615     }
616     focusCallbackEvents_->SetIsDefaultFocus(isDefaultFocus);
617 }
SetIsDefaultGroupFocus(bool isDefaultGroupFocus)618 void FocusHub::SetIsDefaultGroupFocus(bool isDefaultGroupFocus)
619 {
620     if (!focusCallbackEvents_) {
621         focusCallbackEvents_ = MakeRefPtr<FocusCallbackEvents>();
622     }
623     focusCallbackEvents_->SetIsDefaultGroupFocus(isDefaultGroupFocus);
624 }
625 
RefreshFocus()626 void FocusHub::RefreshFocus()
627 {
628     if (!IsCurrentFocus()) {
629         return;
630     }
631 
632     // lost current focus and request another focus
633     auto parent = GetParentFocusHub();
634 
635     // current node is root node
636     if (!parent) {
637         LostFocus();
638         return;
639     }
640     while (!parent->IsFocusable()) {
641         // parent node is root node
642         if (!parent->GetParentFocusHub()) {
643             parent->LostFocus();
644             return;
645         }
646         parent = parent->GetParentFocusHub();
647     }
648     parent->LostFocus();
649     parent->RequestFocusImmediately();
650 }
651 
OnKeyEvent(const KeyEvent & keyEvent)652 bool FocusHub::OnKeyEvent(const KeyEvent& keyEvent)
653 {
654     if (focusType_ == FocusType::SCOPE) {
655         return OnKeyEventScope(keyEvent);
656     }
657     if (focusType_ == FocusType::NODE) {
658         return OnKeyEventNode(keyEvent);
659     }
660     TAG_LOGW(AceLogTag::ACE_FOCUS, "Current node focus type: %{public}d is invalid.", focusType_);
661     return false;
662 }
663 
OnKeyEventNode(const KeyEvent & keyEvent)664 bool FocusHub::OnKeyEventNode(const KeyEvent& keyEvent)
665 {
666     ACE_DCHECK(IsCurrentFocus());
667 
668     auto retInternal = false;
669     auto pipeline = PipelineContext::GetCurrentContext();
670     bool isBypassInner = keyEvent.IsKey({ KeyCode::KEY_TAB }) && pipeline && pipeline->IsTabJustTriggerOnKeyEvent();
671     if (!isBypassInner && !onKeyEventsInternal_.empty()) {
672         retInternal = ProcessOnKeyEventInternal(keyEvent);
673         TAG_LOGI(AceLogTag::ACE_FOCUS,
674             "OnKeyEventInteral: Node %{public}s/%{public}d handle KeyEvent(%{public}d, %{public}d) return: %{public}d",
675             GetFrameName().c_str(), GetFrameId(), keyEvent.code, keyEvent.action, retInternal);
676     }
677 
678     auto info = KeyEventInfo(keyEvent);
679     if (pipeline &&
680         (pipeline->IsKeyInPressed(KeyCode::KEY_META_LEFT) || pipeline->IsKeyInPressed(KeyCode::KEY_META_RIGHT))) {
681         info.SetMetaKey(1);
682     }
683     auto retCallback = false;
684     auto onKeyEventCallback = GetOnKeyCallback();
685     if (onKeyEventCallback) {
686         onKeyEventCallback(info);
687         retCallback = info.IsStopPropagation();
688         TAG_LOGI(AceLogTag::ACE_FOCUS,
689             "OnKeyEventUser: Node %{public}s/%{public}d handle KeyEvent(%{public}d, %{public}d) return: %{public}d",
690             GetFrameName().c_str(), GetFrameId(), keyEvent.code, keyEvent.action, retCallback);
691     }
692 
693     if (!retInternal && !retCallback && keyEvent.action == KeyAction::DOWN) {
694         auto ret = false;
695         switch (keyEvent.code) {
696             case KeyCode::KEY_SPACE:
697             case KeyCode::KEY_ENTER:
698             case KeyCode::KEY_NUMPAD_ENTER:
699                 ret = OnClick(keyEvent);
700                 TAG_LOGI(AceLogTag::ACE_FOCUS,
701                     "OnClick: Node %{public}s/%{public}d handle KeyEvent(%{public}d, %{public}d) return: %{public}d",
702                     GetFrameName().c_str(), GetFrameId(), keyEvent.code, keyEvent.action, ret);
703                 break;
704             default:;
705         }
706         return ret;
707     }
708     return retInternal || retCallback;
709 }
710 
OnKeyEventScope(const KeyEvent & keyEvent)711 bool FocusHub::OnKeyEventScope(const KeyEvent& keyEvent)
712 {
713     ACE_DCHECK(IsCurrentFocus());
714     std::list<RefPtr<FocusHub>> focusNodes;
715     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
716     if (lastFocusNode && lastFocusNode->HandleKeyEvent(keyEvent)) {
717         TAG_LOGD(AceLogTag::ACE_FOCUS,
718             "OnKeyEvent: Node %{public}s/%{public}d will not handle KeyEvent(code:%{public}d, action:%{public}d). "
719             "Because its child %{public}s/%{public}d already has consumed this event.",
720             GetFrameName().c_str(), GetFrameId(), keyEvent.code, keyEvent.action, lastFocusNode->GetFrameName().c_str(),
721             lastFocusNode->GetFrameId());
722         return true;
723     }
724 
725     if (OnKeyEventNode(keyEvent)) {
726         return true;
727     }
728 
729     if (keyEvent.action != KeyAction::DOWN) {
730         return false;
731     }
732 
733     auto pipeline = PipelineContext::GetCurrentContext();
734     CHECK_NULL_RETURN(pipeline, false);
735     if (!pipeline->GetIsFocusActive()) {
736         return false;
737     }
738     if (keyEvent.IsKey({ KeyCode::KEY_TAB }) && pipeline->IsTabJustTriggerOnKeyEvent()) {
739         ScrollToLastFocusIndex();
740         return false;
741     }
742 
743     ScrollToLastFocusIndex();
744     if (!CalculatePosition()) {
745         return false;
746     }
747 
748     switch (keyEvent.code) {
749         case KeyCode::TV_CONTROL_UP:
750             return RequestNextFocus(FocusStep::UP, GetRect());
751         case KeyCode::TV_CONTROL_DOWN:
752             return RequestNextFocus(FocusStep::DOWN, GetRect());
753         case KeyCode::TV_CONTROL_LEFT:
754             return RequestNextFocus(FocusStep::LEFT, GetRect());
755         case KeyCode::TV_CONTROL_RIGHT:
756             return RequestNextFocus(FocusStep::RIGHT, GetRect());
757         case KeyCode::KEY_TAB: {
758             auto context = NG::PipelineContext::GetCurrentContext();
759             bool ret = false;
760             if (keyEvent.pressedCodes.size() == 1) {
761                 context->SetIsFocusingByTab(true);
762                 ret = RequestNextFocus(FocusStep::TAB, GetRect());
763                 auto focusParent = GetParentFocusHub();
764                 if (!focusParent || !focusParent->IsCurrentFocus()) {
765                     if (context->IsFocusWindowIdSetted()) {
766                         FocusToHeadOrTailChild(true);
767                         return false;
768                     }
769                     ret = FocusToHeadOrTailChild(true);
770                 }
771                 context->SetIsFocusingByTab(false);
772             } else if (keyEvent.IsShiftWith(KeyCode::KEY_TAB)) {
773                 context->SetIsFocusingByTab(true);
774                 ret = RequestNextFocus(FocusStep::SHIFT_TAB, GetRect());
775                 auto focusParent = GetParentFocusHub();
776                 if (!focusParent || !focusParent->IsCurrentFocus()) {
777                     if (context->IsFocusWindowIdSetted()) {
778                         FocusToHeadOrTailChild(false);
779                         return false;
780                     }
781                     ret = FocusToHeadOrTailChild(false);
782                 }
783                 context->SetIsFocusingByTab(false);
784             }
785             return ret;
786         }
787         case KeyCode::KEY_MOVE_HOME:
788             return RequestNextFocus(FocusStep::LEFT_END, GetRect()) || RequestNextFocus(FocusStep::UP_END, GetRect());
789         case KeyCode::KEY_MOVE_END:
790             return RequestNextFocus(FocusStep::RIGHT_END, GetRect()) ||
791                    RequestNextFocus(FocusStep::DOWN_END, GetRect());
792         default:
793             return false;
794     }
795 }
796 
RequestFocus() const797 void FocusHub::RequestFocus() const
798 {
799     if (IsCurrentFocus()) {
800         return;
801     }
802     auto context = NG::PipelineContext::GetCurrentContext();
803     CHECK_NULL_VOID(context);
804     context->AddDirtyFocus(GetFrameNode());
805 }
806 
RequestFocusWithDefaultFocusFirstly()807 void FocusHub::RequestFocusWithDefaultFocusFirstly()
808 {
809     TAG_LOGD(AceLogTag::ACE_FOCUS, "Request focus with default focus on node: %{public}s/%{public}d.",
810         GetFrameName().c_str(), GetFrameId());
811     auto pipeline = PipelineContext::GetCurrentContext();
812     CHECK_NULL_VOID(pipeline);
813 
814     RefPtr<FocusHub> viewScope;
815     if (GetFrameName() == V2::MENU_WRAPPER_ETS_TAG) {
816         viewScope = GetChildren().front();
817     } else {
818         viewScope = Claim(this);
819     }
820     if (!viewScope) {
821         pipeline->AddDirtyDefaultFocus(GetFrameNode());
822         return;
823     }
824 
825     auto screenNode = pipeline->GetScreenNode();
826     if (!screenNode || viewScope->GetFrameName() != V2::PAGE_ETS_TAG) {
827         auto viewRootScope = viewScope->GetMainViewRootScope();
828         if (viewRootScope && viewScope->GetIsViewRootScopeFocused()) {
829             viewRootScope->SetFocusDependence(FocusDependence::SELF);
830         }
831     }
832 
833     pipeline->AddDirtyDefaultFocus(viewScope->GetFrameNode());
834 }
835 
RequestNextFocus(FocusStep moveStep,const RectF & rect)836 bool FocusHub::RequestNextFocus(FocusStep moveStep, const RectF& rect)
837 {
838     TAG_LOGI(AceLogTag::ACE_FOCUS, "Request next focus on node: %{public}s/%{public}d by step: %{public}d.",
839         GetFrameName().c_str(), GetFrameId(), moveStep);
840     SetScopeFocusAlgorithm();
841     if (!focusAlgorithm_.getNextFocusNode) {
842         if (focusAlgorithm_.scopeType == ScopeType::PROJECT_AREA) {
843             auto lastFocusNode = lastWeakFocusNode_.Upgrade();
844             CHECK_NULL_RETURN(lastFocusNode, false);
845             RefPtr<FocusHub> nextFocusHub = nullptr;
846             if (IsFocusStepTab(moveStep)) {
847                 nextFocusHub = lastFocusNode->GetNearestNodeByProjectArea(
848                     GetChildren(), moveStep == FocusStep::TAB ? FocusStep::RIGHT : FocusStep::LEFT);
849             }
850             if (!nextFocusHub) {
851                 nextFocusHub = lastFocusNode->GetNearestNodeByProjectArea(GetChildren(), moveStep);
852             }
853             if (!nextFocusHub || nextFocusHub == lastFocusNode) {
854                 TAG_LOGI(
855                     AceLogTag::ACE_FOCUS, "Request next focus failed becase cannot find next node by project area.");
856                 return false;
857             }
858             auto ret = TryRequestFocus(nextFocusHub, rect, moveStep);
859             TAG_LOGI(AceLogTag::ACE_FOCUS,
860                 "Request next focus by project area. Next focus node is %{public}s/%{public}d. Return %{public}d",
861                 nextFocusHub->GetFrameName().c_str(), nextFocusHub->GetFrameId(), ret);
862             return ret;
863         }
864         if (!IsFocusStepTab(moveStep) && focusAlgorithm_.isVertical != IsFocusStepVertical(moveStep)) {
865             TAG_LOGI(AceLogTag::ACE_FOCUS,
866                 "Request next focus failed because direction of node(%{public}d) is different with step(%{public}d).",
867                 focusAlgorithm_.isVertical, moveStep);
868             return false;
869         }
870         auto ret = GoToNextFocusLinear(moveStep, rect);
871         TAG_LOGI(AceLogTag::ACE_FOCUS, "Request next focus by default linear algorithm. Return %{public}d.", ret);
872         return ret;
873     }
874     if (!lastWeakFocusNode_.Upgrade()) {
875         return false;
876     }
877     WeakPtr<FocusHub> nextFocusHubWeak;
878     focusAlgorithm_.getNextFocusNode(moveStep, lastWeakFocusNode_, nextFocusHubWeak);
879     auto nextFocusHub = nextFocusHubWeak.Upgrade();
880     if (!nextFocusHub || nextFocusHub == lastWeakFocusNode_.Upgrade()) {
881         TAG_LOGI(AceLogTag::ACE_FOCUS, "Request next focus failed by custom focus algorithm.");
882         return false;
883     }
884     auto ret = TryRequestFocus(nextFocusHub, rect, moveStep);
885     TAG_LOGI(AceLogTag::ACE_FOCUS,
886         "Request next focus by custom focus algorithm. Next focus node is %{public}s/%{public}d. Return %{public}d",
887         nextFocusHub->GetFrameName().c_str(), nextFocusHub->GetFrameId(), ret);
888     return ret;
889 }
890 
FocusToHeadOrTailChild(bool isHead)891 bool FocusHub::FocusToHeadOrTailChild(bool isHead)
892 {
893     if (!IsFocusableWholePath()) {
894         return false;
895     }
896     if (focusType_ != FocusType::SCOPE || (focusType_ == FocusType::SCOPE && focusDepend_ == FocusDependence::SELF)) {
897         return RequestFocusImmediately();
898     }
899 
900     std::list<RefPtr<FocusHub>> focusNodes;
901     FlushChildrenFocusHub(focusNodes);
902     bool canChildBeFocused = false;
903     if (isHead) {
904         canChildBeFocused = std::any_of(focusNodes.begin(), focusNodes.end(),
905             [](const RefPtr<FocusHub>& node) { return node->FocusToHeadOrTailChild(true); });
906     } else {
907         canChildBeFocused = std::any_of(focusNodes.rbegin(), focusNodes.rend(),
908             [](const RefPtr<FocusHub>& node) { return node->FocusToHeadOrTailChild(false); });
909     }
910 
911     if (focusDepend_ == FocusDependence::CHILD) {
912         return canChildBeFocused;
913     }
914     if (focusDepend_ == FocusDependence::AUTO) {
915         if (!canChildBeFocused) {
916             return RequestFocusImmediately();
917         }
918         return canChildBeFocused;
919     }
920     return false;
921 }
922 
OnClick(const KeyEvent & event)923 bool FocusHub::OnClick(const KeyEvent& event)
924 {
925     auto onClickCallback = GetOnClickCallback();
926     if (onClickCallback) {
927         auto info = GestureEvent();
928         info.SetTimeStamp(event.timeStamp);
929         auto geometryNode = GetGeometryNode();
930         CHECK_NULL_RETURN(geometryNode, false);
931         auto rect = geometryNode->GetFrameRect();
932         info.SetGlobalLocation(Offset((rect.Left() + rect.Right()) / 2, (rect.Top() + rect.Bottom()) / 2));
933         info.SetLocalLocation(Offset((rect.Right() - rect.Left()) / 2, (rect.Bottom() - rect.Top()) / 2));
934         info.SetSourceDevice(event.sourceType);
935         info.SetDeviceId(event.deviceId);
936         onClickCallback(info);
937         return true;
938     }
939     return false;
940 }
941 
SwitchFocus(const RefPtr<FocusHub> & focusNode)942 void FocusHub::SwitchFocus(const RefPtr<FocusHub>& focusNode)
943 {
944     if (focusType_ != FocusType::SCOPE) {
945         TAG_LOGW(AceLogTag::ACE_FOCUS, "SwitchFocus: parent focus node is not a scope!");
946         return;
947     }
948     std::list<RefPtr<FocusHub>> focusNodes;
949     FlushChildrenFocusHub(focusNodes);
950 
951     auto focusNodeNeedBlur = lastWeakFocusNode_.Upgrade();
952     lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(focusNode));
953 
954     TAG_LOGD(AceLogTag::ACE_FOCUS, "Switch focus from %{public}s/%{public}d to %{public}s/%{public}d",
955         focusNodeNeedBlur ? focusNodeNeedBlur->GetFrameName().c_str() : "NULL",
956         focusNodeNeedBlur ? focusNodeNeedBlur->GetFrameId() : -1, focusNode->GetFrameName().c_str(),
957         focusNode->GetFrameId());
958     if (IsCurrentFocus()) {
959         if (focusNodeNeedBlur && focusNodeNeedBlur != focusNode) {
960             focusNodeNeedBlur->LostFocus();
961         }
962     } else {
963         RequestFocusImmediately();
964     }
965 }
966 
GoToNextFocusLinear(FocusStep step,const RectF & rect)967 bool FocusHub::GoToNextFocusLinear(FocusStep step, const RectF& rect)
968 {
969     if (step == FocusStep::NONE) {
970         return false;
971     }
972     bool reverse = !IsFocusStepForward(step);
973     if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
974         reverse = !reverse;
975     }
976     std::list<RefPtr<FocusHub>> focusNodes;
977     auto itNewFocusNode = FlushChildrenFocusHub(focusNodes);
978     if (focusNodes.empty()) {
979         return false;
980     }
981     if (itNewFocusNode == focusNodes.end()) {
982         itNewFocusNode = focusNodes.begin();
983     }
984     if (reverse) {
985         if (itNewFocusNode == focusNodes.begin()) {
986             itNewFocusNode = focusNodes.end();
987             return false;
988         }
989         --itNewFocusNode;
990 
991         while (itNewFocusNode != focusNodes.begin()) {
992             if (TryRequestFocus(*itNewFocusNode, rect, step)) {
993                 return true;
994             }
995             --itNewFocusNode;
996         }
997         if (itNewFocusNode == focusNodes.begin()) {
998             if (TryRequestFocus(*itNewFocusNode, rect, step)) {
999                 return true;
1000             }
1001         }
1002     } else {
1003         if (itNewFocusNode != focusNodes.end()) {
1004             ++itNewFocusNode;
1005         }
1006         while (itNewFocusNode != focusNodes.end()) {
1007             if (TryRequestFocus(*itNewFocusNode, rect, step)) {
1008                 return true;
1009             }
1010             ++itNewFocusNode;
1011         }
1012     }
1013 
1014     return false;
1015 }
1016 
TryRequestFocus(const RefPtr<FocusHub> & focusNode,const RectF & rect,FocusStep step)1017 bool FocusHub::TryRequestFocus(const RefPtr<FocusHub>& focusNode, const RectF& rect, FocusStep step)
1018 {
1019     if (IsFocusStepTab(step) && focusNode->AcceptFocusOfSpecifyChild(step)) {
1020         return focusNode->RequestFocusImmediately();
1021     }
1022     if (rect.IsValid()) {
1023         RectF childRect;
1024         if (!CalculateRect(focusNode, childRect) ||
1025             !focusNode->AcceptFocusByRectOfLastFocus(rect - childRect.GetOffset())) {
1026             return false;
1027         }
1028     }
1029     return focusNode->RequestFocusImmediately();
1030 }
1031 
CalculatePosition()1032 bool FocusHub::CalculatePosition()
1033 {
1034     std::list<RefPtr<FocusHub>> focusNodes;
1035     FlushChildrenFocusHub(focusNodes);
1036     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
1037     CHECK_NULL_RETURN(lastFocusNode, false);
1038 
1039     RectF childRect;
1040     if (!CalculateRect(lastFocusNode, childRect)) {
1041         return false;
1042     }
1043 
1044     if (lastFocusNode->IsChild()) {
1045         auto lastFocusGeometryNode = lastFocusNode->GetGeometryNode();
1046         CHECK_NULL_RETURN(lastFocusGeometryNode, false);
1047         RectF rect(childRect.GetOffset(), lastFocusGeometryNode->GetFrameSize());
1048         lastFocusNode->SetRect(rect);
1049         SetRect(rect);
1050     } else {
1051         SetRect(lastFocusNode->GetRect() + childRect.GetOffset());
1052     }
1053 
1054     return true;
1055 }
1056 
SetScopeFocusAlgorithm()1057 void FocusHub::SetScopeFocusAlgorithm()
1058 {
1059     auto frame = GetFrameNode();
1060     CHECK_NULL_VOID(frame);
1061     auto pattern = frame->GetPattern();
1062     CHECK_NULL_VOID(pattern);
1063     focusAlgorithm_ = pattern->GetScopeFocusAlgorithm();
1064 }
1065 
SetLastFocusNodeIndex(const RefPtr<FocusHub> & focusNode)1066 void FocusHub::SetLastFocusNodeIndex(const RefPtr<FocusHub>& focusNode)
1067 {
1068     auto frame = GetFrameNode();
1069     CHECK_NULL_VOID(frame);
1070     auto pattern = frame->GetPattern();
1071     CHECK_NULL_VOID(pattern);
1072     lastFocusNodeIndex_ = pattern->GetFocusNodeIndex(focusNode);
1073 }
1074 
ScrollToLastFocusIndex() const1075 void FocusHub::ScrollToLastFocusIndex() const
1076 {
1077     if (lastFocusNodeIndex_ == -1) {
1078         return;
1079     }
1080     auto frame = GetFrameNode();
1081     CHECK_NULL_VOID(frame);
1082     auto pattern = frame->GetPattern();
1083     CHECK_NULL_VOID(pattern);
1084     pattern->ScrollToFocusNodeIndex(lastFocusNodeIndex_);
1085 }
1086 
OnFocus()1087 void FocusHub::OnFocus()
1088 {
1089     if (focusType_ == FocusType::NODE) {
1090         OnFocusNode();
1091     } else if (focusType_ == FocusType::SCOPE) {
1092         OnFocusScope();
1093     }
1094     auto frameNode = GetFrameNode();
1095     CHECK_NULL_VOID(frameNode);
1096     auto curPattern = frameNode->GetPattern<NG::Pattern>();
1097     CHECK_NULL_VOID(curPattern);
1098     bool isNeedKeyboard = curPattern->NeedSoftKeyboard();
1099     auto pipeline = PipelineContext::GetCurrentContext();
1100     CHECK_NULL_VOID(pipeline);
1101     pipeline->SetNeedSoftKeyboard(isNeedKeyboard);
1102 }
1103 
OnBlur()1104 void FocusHub::OnBlur()
1105 {
1106     if (focusType_ == FocusType::NODE) {
1107         OnBlurNode();
1108     } else if (focusType_ == FocusType::SCOPE) {
1109         OnBlurScope();
1110     }
1111     auto pipeline = PipelineContext::GetCurrentContext();
1112     CHECK_NULL_VOID(pipeline);
1113     if (blurReason_ != BlurReason::WINDOW_BLUR) {
1114         pipeline->SetNeedSoftKeyboard(false);
1115     } else {
1116         pipeline->SetNeedSoftKeyboard(std::nullopt);
1117     }
1118 }
1119 
IsCloseKeyboard(RefPtr<FrameNode> frameNode)1120 void FocusHub::IsCloseKeyboard(RefPtr<FrameNode> frameNode)
1121 {
1122 #if defined(ENABLE_STANDARD_INPUT)
1123     // If focus pattern does not need softkeyboard, close it, not in windowScene.
1124     auto curPattern = frameNode->GetPattern<NG::Pattern>();
1125     CHECK_NULL_VOID(curPattern);
1126     bool isNeedKeyBoard = curPattern->NeedSoftKeyboard();
1127     if (!isNeedKeyBoard) {
1128         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "FrameNode(%{public}s/%{public}d) notNeedSoftKeyboard.",
1129             frameNode->GetTag().c_str(), frameNode->GetId());
1130         auto inputMethod = MiscServices::InputMethodController::GetInstance();
1131         if (inputMethod) {
1132             TAG_LOGI(AceLogTag::ACE_KEYBOARD, "SoftKeyboard Closes Successfully.");
1133             inputMethod->Close();
1134         }
1135     }
1136 #endif
1137 }
1138 
NavCloseKeyboard()1139 void FocusHub::NavCloseKeyboard()
1140 {
1141 #if defined(ENABLE_STANDARD_INPUT)
1142     // If Nav, close it
1143     TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Nav CloseKeyboard FrameNode notNeedSoftKeyboard.");
1144     auto inputMethod = MiscServices::InputMethodController::GetInstance();
1145     if (inputMethod) {
1146         inputMethod->RequestHideInput();
1147         inputMethod->Close();
1148         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Nav CloseKeyboard SoftKeyboard Closes Successfully.");
1149     }
1150 #endif
1151 }
1152 
PushPageCloseKeyboard()1153 void FocusHub::PushPageCloseKeyboard()
1154 {
1155 #if defined(ENABLE_STANDARD_INPUT)
1156     // If pushpage, close it
1157     TAG_LOGI(AceLogTag::ACE_KEYBOARD, "PageChange CloseKeyboard FrameNode notNeedSoftKeyboard.");
1158     auto inputMethod = MiscServices::InputMethodController::GetInstance();
1159     if (inputMethod) {
1160         inputMethod->Close();
1161         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "PageChange CloseKeyboard SoftKeyboard Closes Successfully.");
1162     }
1163 #endif
1164 }
1165 
OnFocusNode()1166 void FocusHub::OnFocusNode()
1167 {
1168     TAG_LOGI(AceLogTag::ACE_FOCUS, "Node(%{public}s/%{public}d) on focus", GetFrameName().c_str(), GetFrameId());
1169     if (onFocusInternal_) {
1170         onFocusInternal_();
1171     }
1172     auto pipeline = PipelineContext::GetCurrentContext();
1173     CHECK_NULL_VOID(pipeline);
1174     pipeline->AddAfterLayoutTask([weak = WeakClaim(this)]() {
1175         auto focusHub = weak.Upgrade();
1176         CHECK_NULL_VOID(focusHub);
1177         auto onFocusCallback = focusHub->GetOnFocusCallback();
1178         if (onFocusCallback) {
1179             onFocusCallback();
1180         }
1181     });
1182     auto parentFocusHub = GetParentFocusHub();
1183     if (parentFocusHub) {
1184         parentFocusHub->SetLastFocusNodeIndex(AceType::Claim(this));
1185     }
1186     HandleParentScroll(); // If current focus node has a scroll parent. Handle the scroll event.
1187     auto rootNode = pipeline->GetRootElement();
1188     auto rootFocusHub = rootNode ? rootNode->GetFocusHub() : nullptr;
1189     if (rootFocusHub && pipeline->GetIsFocusActive()) {
1190         rootFocusHub->ClearAllFocusState();
1191         rootFocusHub->PaintAllFocusState();
1192     }
1193     auto frameNode = GetFrameNode();
1194     CHECK_NULL_VOID(frameNode);
1195     frameNode->OnAccessibilityEvent(AccessibilityEventType::FOCUS);
1196 
1197     if (frameNode->GetFocusType() == FocusType::NODE) {
1198         pipeline->SetFocusNode(frameNode);
1199     }
1200 
1201     pipeline->RequestFrame();
1202 }
1203 
OnBlurNode()1204 void FocusHub::OnBlurNode()
1205 {
1206     TAG_LOGI(AceLogTag::ACE_FOCUS, "Node(%{public}s/%{public}d) on blur by %{public}d", GetFrameName().c_str(),
1207         GetFrameId(), blurReason_);
1208     if (onBlurInternal_) {
1209         onBlurInternal_();
1210     }
1211     if (onBlurReasonInternal_) {
1212         onBlurReasonInternal_(blurReason_);
1213     }
1214     auto pipeline = PipelineContext::GetCurrentContext();
1215     CHECK_NULL_VOID(pipeline);
1216     pipeline->AddAfterLayoutTask([weak = WeakClaim(this)]() {
1217         auto focusHub = weak.Upgrade();
1218         CHECK_NULL_VOID(focusHub);
1219         auto onBlurCallback = focusHub->GetOnBlurCallback();
1220         if (onBlurCallback) {
1221             onBlurCallback();
1222         }
1223     });
1224     if (blurReason_ != BlurReason::FRAME_DESTROY) {
1225         ClearFocusState();
1226     }
1227     auto rootNode = pipeline->GetRootElement();
1228     auto rootFocusHub = rootNode ? rootNode->GetFocusHub() : nullptr;
1229     if (rootFocusHub && pipeline->GetIsFocusActive()) {
1230         rootFocusHub->ClearAllFocusState();
1231         rootFocusHub->PaintAllFocusState();
1232     }
1233     auto frameNode = GetFrameNode();
1234     CHECK_NULL_VOID(frameNode);
1235     if (frameNode->GetFocusType() == FocusType::NODE && frameNode == pipeline->GetFocusNode()) {
1236         pipeline->SetFocusNode(nullptr);
1237     }
1238 
1239     pipeline->RequestFrame();
1240 }
1241 
CheckFocusStateStyle(bool onFocus)1242 void FocusHub::CheckFocusStateStyle(bool onFocus)
1243 {
1244     auto eventHub = eventHub_.Upgrade();
1245     CHECK_NULL_VOID(eventHub);
1246     if (onFocus) {
1247         eventHub->UpdateCurrentUIState(UI_STATE_FOCUSED);
1248     } else {
1249         eventHub->ResetCurrentUIState(UI_STATE_FOCUSED);
1250     }
1251 }
1252 
HasFocusStateStyle()1253 bool FocusHub::HasFocusStateStyle()
1254 {
1255     auto eventHub = eventHub_.Upgrade();
1256     CHECK_NULL_RETURN(eventHub, false);
1257     return eventHub->HasStateStyle(UI_STATE_FOCUSED);
1258 }
1259 
OnFocusScope(bool currentHasFocused)1260 void FocusHub::OnFocusScope(bool currentHasFocused)
1261 {
1262     if (focusDepend_ == FocusDependence::SELF) {
1263         lastWeakFocusNode_ = nullptr;
1264         OnFocusNode();
1265         return;
1266     }
1267 
1268     std::list<RefPtr<FocusHub>> focusNodes;
1269     auto itLastFocusNode = FlushChildrenFocusHub(focusNodes);
1270     bool isAnyChildFocusable = focusNodes.empty()
1271                                    ? false
1272                                    : std::any_of(focusNodes.begin(), focusNodes.end(),
1273                                          [](const RefPtr<FocusHub>& focusNode) { return focusNode->IsFocusable(); });
1274 
1275     if (focusDepend_ == FocusDependence::AUTO && !isAnyChildFocusable) {
1276         lastWeakFocusNode_ = nullptr;
1277         OnFocusNode();
1278         return;
1279     }
1280 
1281     if ((focusDepend_ == FocusDependence::AUTO || focusDepend_ == FocusDependence::CHILD) && isAnyChildFocusable) {
1282         auto itFocusNode = itLastFocusNode;
1283         do {
1284             if (itLastFocusNode == focusNodes.end()) {
1285                 itLastFocusNode = focusNodes.begin();
1286                 lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*itLastFocusNode));
1287                 if (itLastFocusNode == itFocusNode) {
1288                     break;
1289                 }
1290             }
1291             lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*itLastFocusNode));
1292             if ((*itLastFocusNode)->RequestFocusImmediately()) {
1293                 if (!currentHasFocused) {
1294                     OnFocusNode();
1295                 }
1296                 return;
1297             }
1298         } while ((++itLastFocusNode) != itFocusNode);
1299 
1300         // Not found any focusable node, clear focus.
1301         itLastFocusNode = focusNodes.end();
1302         lastWeakFocusNode_ = nullptr;
1303     }
1304 }
1305 
OnBlurScope()1306 void FocusHub::OnBlurScope()
1307 {
1308     std::list<RefPtr<FocusHub>> focusNodes;
1309     FlushChildrenFocusHub(focusNodes);
1310     OnBlurNode();
1311     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
1312     if (lastFocusNode) {
1313         lastFocusNode->LostFocus(blurReason_);
1314     }
1315 }
1316 
PaintFocusState(bool isNeedStateStyles,bool forceUpdate)1317 bool FocusHub::PaintFocusState(bool isNeedStateStyles, bool forceUpdate)
1318 {
1319     auto context = PipelineContext::GetCurrentContext();
1320     CHECK_NULL_RETURN(context, false);
1321     auto frameNode = GetFrameNode();
1322     CHECK_NULL_RETURN(frameNode, false);
1323     auto renderContext = frameNode->GetRenderContext();
1324     CHECK_NULL_RETURN(renderContext, false);
1325     if (!forceUpdate && (!context->GetIsFocusActive() || !IsNeedPaintFocusState())) {
1326         return false;
1327     }
1328 
1329     if (HasFocusStateStyle()) {
1330         if (isNeedStateStyles) {
1331             // do focus state style.
1332             CheckFocusStateStyle(true);
1333         }
1334         return true;
1335     }
1336 
1337     if (focusStyleType_ == FocusStyleType::NONE) {
1338         return false;
1339     }
1340 
1341     if (focusStyleType_ == FocusStyleType::CUSTOM_REGION) {
1342         CHECK_NULL_RETURN(getInnerFocusRectFunc_, false);
1343         RoundRect focusRectInner;
1344         focusRectInner.SetRect({ -1, -1, -1, -1 });
1345         getInnerFocusRectFunc_(focusRectInner);
1346         if (!focusRectInner.GetRect().IsValid()) {
1347             return false;
1348         }
1349         return PaintInnerFocusState(focusRectInner, forceUpdate);
1350     }
1351 
1352     auto appTheme = context->GetTheme<AppTheme>();
1353     CHECK_NULL_RETURN(appTheme, false);
1354     Color paintColor;
1355     if (HasPaintColor()) {
1356         paintColor = GetPaintColor();
1357     } else {
1358         paintColor = appTheme->GetFocusColor();
1359     }
1360     Dimension paintWidth;
1361     if (HasPaintWidth()) {
1362         paintWidth = GetPaintWidth();
1363     } else {
1364         paintWidth = appTheme->GetFocusWidthVp();
1365     }
1366 
1367     if (focusStyleType_ == FocusStyleType::CUSTOM_BORDER) {
1368         if (!HasPaintRect()) {
1369             return false;
1370         }
1371         renderContext->PaintFocusState(GetPaintRect(), paintColor, paintWidth);
1372         return true;
1373     }
1374 
1375     Dimension focusPaddingVp = Dimension(0.0, DimensionUnit::VP);
1376     if (HasFocusPadding()) {
1377         focusPaddingVp = GetFocusPadding();
1378     } else {
1379         if (focusStyleType_ == FocusStyleType::INNER_BORDER) {
1380             focusPaddingVp = -appTheme->GetFocusWidthVp();
1381         } else if (focusStyleType_ == FocusStyleType::OUTER_BORDER) {
1382             focusPaddingVp = appTheme->GetFocusOutPaddingVp();
1383         }
1384     }
1385     if (HasPaintRect()) {
1386         renderContext->PaintFocusState(GetPaintRect(), focusPaddingVp, paintColor, paintWidth);
1387     } else {
1388         renderContext->PaintFocusState(focusPaddingVp, paintColor, paintWidth);
1389     }
1390     return true;
1391 }
1392 
PaintAllFocusState()1393 bool FocusHub::PaintAllFocusState()
1394 {
1395     if (PaintFocusState()) {
1396         return !isFocusActiveWhenFocused_;
1397     }
1398     std::list<RefPtr<FocusHub>> focusNodes;
1399     FlushChildrenFocusHub(focusNodes);
1400     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
1401     if (lastFocusNode && lastFocusNode->IsCurrentFocus() && lastFocusNode->IsFocusableNode()) {
1402         return lastFocusNode->PaintAllFocusState();
1403     }
1404     if (onPaintFocusStateCallback_) {
1405         return onPaintFocusStateCallback_();
1406     }
1407     return false;
1408 }
1409 
PaintInnerFocusState(const RoundRect & paintRect,bool forceUpdate)1410 bool FocusHub::PaintInnerFocusState(const RoundRect& paintRect, bool forceUpdate)
1411 {
1412     auto context = PipelineContext::GetCurrentContext();
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 (!forceUpdate && (!context->GetIsFocusActive() || !IsNeedPaintFocusState())) {
1419         return false;
1420     }
1421     auto appTheme = context->GetTheme<AppTheme>();
1422     CHECK_NULL_RETURN(appTheme, false);
1423     Color paintColor;
1424     if (HasPaintColor()) {
1425         paintColor = GetPaintColor();
1426     } else {
1427         paintColor = appTheme->GetFocusColor();
1428     }
1429     Dimension paintWidth;
1430     if (HasPaintWidth()) {
1431         paintWidth = GetPaintWidth();
1432     } else {
1433         paintWidth = appTheme->GetFocusWidthVp();
1434     }
1435     renderContext->ClearFocusState();
1436     renderContext->PaintFocusState(paintRect, paintColor, paintWidth);
1437     return true;
1438 }
1439 
ClearFocusState(bool isNeedStateStyles)1440 void FocusHub::ClearFocusState(bool isNeedStateStyles)
1441 {
1442     if (isNeedStateStyles) {
1443         // check focus state style.
1444         CheckFocusStateStyle(false);
1445     }
1446     if (onClearFocusStateCallback_) {
1447         onClearFocusStateCallback_();
1448     }
1449     if (focusStyleType_ != FocusStyleType::NONE) {
1450         auto frameNode = GetFrameNode();
1451         CHECK_NULL_VOID(frameNode);
1452         auto renderContext = frameNode->GetRenderContext();
1453         CHECK_NULL_VOID(renderContext);
1454         renderContext->ClearFocusState();
1455     }
1456 }
1457 
ClearAllFocusState()1458 void FocusHub::ClearAllFocusState()
1459 {
1460     ClearFocusState();
1461     std::list<RefPtr<FocusHub>> focusNodes;
1462     FlushChildrenFocusHub(focusNodes);
1463     auto lastFocusNode = lastWeakFocusNode_.Upgrade();
1464     if (lastFocusNode) {
1465         lastFocusNode->ClearAllFocusState();
1466     }
1467 }
1468 
IsNeedPaintFocusState()1469 bool FocusHub::IsNeedPaintFocusState()
1470 {
1471     if (currentFocus_ && IsFocusableNode() &&
1472         (focusDepend_ == FocusDependence::SELF || focusType_ == FocusType::NODE)) {
1473         return focusStyleType_ != FocusStyleType::NONE || HasFocusStateStyle();
1474     }
1475     std::list<RefPtr<FocusHub>> focusNodes;
1476     FlushChildrenFocusHub(focusNodes);
1477     auto lastFocusNode = GetLastWeakFocusNode().Upgrade();
1478     while (lastFocusNode) {
1479         if (!lastFocusNode->IsCurrentFocus() || !lastFocusNode->IsFocusableNode()) {
1480             break;
1481         }
1482         if (lastFocusNode->GetFocusStyleType() != FocusStyleType::NONE || lastFocusNode->HasFocusStateStyle()) {
1483             return false;
1484         }
1485         focusNodes.clear();
1486         lastFocusNode->FlushChildrenFocusHub(focusNodes);
1487         lastFocusNode = lastFocusNode->GetLastWeakFocusNode().Upgrade();
1488     }
1489     return focusStyleType_ != FocusStyleType::NONE || HasFocusStateStyle();
1490 }
1491 
AcceptFocusOfSpecifyChild(FocusStep step)1492 bool FocusHub::AcceptFocusOfSpecifyChild(FocusStep step)
1493 {
1494     if (focusType_ == FocusType::NODE) {
1495         return IsFocusable();
1496     }
1497     if (focusType_ != FocusType::SCOPE || !IsFocusableScope()) {
1498         return false;
1499     }
1500     if (focusDepend_ == FocusDependence::SELF) {
1501         return true;
1502     }
1503     std::list<RefPtr<FocusHub>> focusNodes;
1504     FlushChildrenFocusHub(focusNodes);
1505     bool canChildBeFocused = false;
1506     if (!focusNodes.empty()) {
1507         if (step == FocusStep::TAB) {
1508             auto iterNewFocusNode = focusNodes.begin();
1509             while (iterNewFocusNode != focusNodes.end()) {
1510                 if (*iterNewFocusNode && (*iterNewFocusNode)->AcceptFocusOfSpecifyChild(step)) {
1511                     lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*iterNewFocusNode));
1512                     canChildBeFocused = true;
1513                     break;
1514                 }
1515                 ++iterNewFocusNode;
1516             }
1517         } else if (step == FocusStep::SHIFT_TAB) {
1518             auto iterNewFocusNode = focusNodes.rbegin();
1519             while (iterNewFocusNode != focusNodes.rend()) {
1520                 if (*iterNewFocusNode && (*iterNewFocusNode)->AcceptFocusOfSpecifyChild(step)) {
1521                     lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*iterNewFocusNode));
1522                     canChildBeFocused = true;
1523                     break;
1524                 }
1525                 ++iterNewFocusNode;
1526             }
1527         }
1528     }
1529     if (focusDepend_ == FocusDependence::CHILD) {
1530         return canChildBeFocused;
1531     }
1532     return focusDepend_ == FocusDependence::AUTO;
1533 }
1534 
AcceptFocusOfLastFocus()1535 bool FocusHub::AcceptFocusOfLastFocus()
1536 {
1537     if (focusType_ == FocusType::SCOPE) {
1538         auto lastFocusNode = lastWeakFocusNode_.Upgrade();
1539         return lastFocusNode ? lastFocusNode->AcceptFocusOfLastFocus() : false;
1540     }
1541     if (focusType_ == FocusType::NODE) {
1542         return IsFocusableWholePath();
1543     }
1544     return false;
1545 }
1546 
AcceptFocusByRectOfLastFocus(const RectF & rect)1547 bool FocusHub::AcceptFocusByRectOfLastFocus(const RectF& rect)
1548 {
1549     if (focusType_ == FocusType::NODE) {
1550         return AcceptFocusByRectOfLastFocusNode(rect);
1551     }
1552     if (focusType_ == FocusType::SCOPE) {
1553         return AcceptFocusByRectOfLastFocusFlex(rect);
1554     }
1555     return false;
1556 }
1557 
AcceptFocusByRectOfLastFocusNode(const RectF & rect)1558 bool FocusHub::AcceptFocusByRectOfLastFocusNode(const RectF& rect)
1559 {
1560     return IsFocusableWholePath();
1561 }
1562 
AcceptFocusByRectOfLastFocusScope(const RectF & rect)1563 bool FocusHub::AcceptFocusByRectOfLastFocusScope(const RectF& rect)
1564 {
1565     std::list<RefPtr<FocusHub>> focusNodes;
1566     auto itLastFocusNode = FlushChildrenFocusHub(focusNodes);
1567     if (focusNodes.empty()) {
1568         return false;
1569     }
1570     auto itFocusNode = itLastFocusNode;
1571     do {
1572         if (itLastFocusNode == focusNodes.end()) {
1573             itLastFocusNode = focusNodes.begin();
1574             lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*itLastFocusNode));
1575             if (itLastFocusNode == itFocusNode) {
1576                 break;
1577             }
1578         }
1579         RectF childRect;
1580         if (!CalculateRect(*itLastFocusNode, childRect)) {
1581             continue;
1582         }
1583 
1584         if ((*itLastFocusNode)->AcceptFocusByRectOfLastFocus(rect - childRect.GetOffset())) {
1585             lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*itLastFocusNode));
1586             return true;
1587         }
1588     } while ((++itLastFocusNode) != itFocusNode);
1589     if (itLastFocusNode == focusNodes.end()) {
1590         lastWeakFocusNode_ = nullptr;
1591     } else {
1592         lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*itLastFocusNode));
1593     }
1594 
1595     return false;
1596 }
1597 
AcceptFocusByRectOfLastFocusFlex(const RectF & rect)1598 bool FocusHub::AcceptFocusByRectOfLastFocusFlex(const RectF& rect)
1599 {
1600     if (!rect.IsValid()) {
1601         return false;
1602     }
1603 
1604     if (focusType_ != FocusType::SCOPE || !IsFocusableWholePath()) {
1605         return false;
1606     }
1607     if (focusDepend_ == FocusDependence::SELF) {
1608         return true;
1609     }
1610     std::list<RefPtr<FocusHub>> focusNodes;
1611     FlushChildrenFocusHub(focusNodes);
1612     bool canChildBeFocused = false;
1613     OffsetF offset;
1614     auto itNewFocusNode = focusNodes.end();
1615     double minVal = std::numeric_limits<double>::max();
1616     for (auto it = focusNodes.begin(); it != focusNodes.end(); ++it) {
1617         if (!(*it)->IsFocusable()) {
1618             continue;
1619         }
1620 
1621         RectF childRect;
1622         if (!CalculateRect(*it, childRect)) {
1623             continue;
1624         }
1625 
1626         if (!childRect.IsValid() || NearZero(childRect.Width()) || NearZero(childRect.Height())) {
1627             continue;
1628         }
1629 
1630         OffsetF vec = childRect.Center() - rect.Center();
1631         double val = (vec.GetX() * vec.GetX()) + (vec.GetY() * vec.GetY());
1632         if (minVal > val) {
1633             minVal = val;
1634             itNewFocusNode = it;
1635             offset = childRect.GetOffset();
1636         }
1637     }
1638 
1639     if (itNewFocusNode != focusNodes.end() && (*itNewFocusNode)->AcceptFocusByRectOfLastFocus(rect - offset)) {
1640         lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*itNewFocusNode));
1641         canChildBeFocused = true;
1642     }
1643     if (focusDepend_ == FocusDependence::CHILD) {
1644         return canChildBeFocused;
1645     }
1646     return focusDepend_ == FocusDependence::AUTO;
1647 }
1648 
CalculateRect(const RefPtr<FocusHub> & childNode,RectF & rect) const1649 bool FocusHub::CalculateRect(const RefPtr<FocusHub>& childNode, RectF& rect) const
1650 {
1651     auto childGeometryNode = childNode->GetGeometryNode();
1652     CHECK_NULL_RETURN(childGeometryNode, false);
1653     rect = childGeometryNode->GetFrameRect();
1654     return true;
1655 }
1656 
IsFocusableByTab()1657 bool FocusHub::IsFocusableByTab()
1658 {
1659     if (focusType_ == FocusType::NODE) {
1660         return IsFocusableNodeByTab();
1661     }
1662     if (focusType_ == FocusType::SCOPE) {
1663         return IsFocusableScopeByTab();
1664     }
1665     return false;
1666 }
1667 
IsFocusableNodeByTab()1668 bool FocusHub::IsFocusableNodeByTab()
1669 {
1670     auto parent = GetParentFocusHub();
1671     CHECK_NULL_RETURN(parent, GetTabIndex() == 0);
1672     return (GetTabIndex() == 0) && (parent->GetTabIndex() == 0);
1673 }
1674 
IsFocusableScopeByTab()1675 bool FocusHub::IsFocusableScopeByTab()
1676 {
1677     std::list<RefPtr<FocusHub>> focusNodes;
1678     FlushChildrenFocusHub(focusNodes);
1679     if (!IsFocusableNodeByTab()) {
1680         return false;
1681     }
1682     if (focusNodes.empty()) {
1683         return true;
1684     }
1685     return std::any_of(focusNodes.begin(), focusNodes.end(),
1686         [](const RefPtr<FocusHub>& focusNode) { return focusNode->IsFocusableByTab(); });
1687 }
1688 
IsFocusableWholePath()1689 bool FocusHub::IsFocusableWholePath()
1690 {
1691     auto parent = GetParentFocusHub();
1692     while (parent) {
1693         if (!parent->IsFocusableNode()) {
1694             return false;
1695         }
1696         parent = parent->GetParentFocusHub();
1697     }
1698     return IsFocusable();
1699 }
1700 
IsOnRootTree() const1701 bool FocusHub::IsOnRootTree() const
1702 {
1703     auto parent = GetParentFocusHub();
1704     while (parent) {
1705         auto parentName = parent->GetFrameName();
1706         if (parentName == V2::ROOT_ETS_TAG) {
1707             return true;
1708         }
1709         parent = parent->GetParentFocusHub();
1710     }
1711     return false;
1712 }
1713 
CollectTabIndexNodes(TabIndexNodeList & tabIndexNodes)1714 void FocusHub::CollectTabIndexNodes(TabIndexNodeList& tabIndexNodes)
1715 {
1716     if (GetTabIndex() > 0 && IsFocusableWholePath()) {
1717         tabIndexNodes.emplace_back(GetTabIndex(), WeakClaim(this));
1718     }
1719     if (GetFocusType() == FocusType::SCOPE) {
1720         std::list<RefPtr<FocusHub>> focusNodes;
1721         FlushChildrenFocusHub(focusNodes);
1722         for (auto& child : focusNodes) {
1723             child->CollectTabIndexNodes(tabIndexNodes);
1724         }
1725     }
1726 }
1727 
GoToFocusByTabNodeIdx(TabIndexNodeList & tabIndexNodes,int32_t tabNodeIdx)1728 bool FocusHub::GoToFocusByTabNodeIdx(TabIndexNodeList& tabIndexNodes, int32_t tabNodeIdx)
1729 {
1730     auto iter = tabIndexNodes.begin();
1731     std::advance(iter, tabNodeIdx);
1732     if (iter == tabIndexNodes.end()) {
1733         return false;
1734     }
1735     auto nodeNeedToFocus = (*iter).second.Upgrade();
1736     if (!nodeNeedToFocus) {
1737         TAG_LOGW(AceLogTag::ACE_FOCUS, "Tab index node is null");
1738         return false;
1739     }
1740     auto nodeIdNeedToFocus = nodeNeedToFocus->GetFrameId();
1741     TAG_LOGI(AceLogTag::ACE_FOCUS, "Move focus to tab index node(%{public}d: %{public}s/%{public}d)", tabNodeIdx,
1742         nodeNeedToFocus->GetFrameName().c_str(), nodeNeedToFocus->GetFrameId());
1743     if (nodeNeedToFocus->GetFocusType() == FocusType::SCOPE && !nodeNeedToFocus->IsDefaultGroupHasFocused()) {
1744         auto defaultFocusNode = nodeNeedToFocus->GetChildFocusNodeByType(FocusNodeType::GROUP_DEFAULT);
1745         if (defaultFocusNode) {
1746             if (!defaultFocusNode->IsFocusableWholePath()) {
1747                 TAG_LOGI(AceLogTag::ACE_FOCUS, "node(%{public}d) is not focusable", tabNodeIdx);
1748                 return false;
1749             }
1750             nodeNeedToFocus->SetIsDefaultGroupHasFocused(true);
1751             if (defaultFocusNode->RequestFocusImmediately()) {
1752                 lastTabIndexNodeId_ = nodeIdNeedToFocus;
1753                 return true;
1754             }
1755             return false;
1756         }
1757     }
1758     if (!nodeNeedToFocus->IsFocusableWholePath()) {
1759         TAG_LOGI(AceLogTag::ACE_FOCUS, "node(%{public}d) is not focusable", tabNodeIdx);
1760         return false;
1761     }
1762     if (nodeNeedToFocus->RequestFocusImmediately()) {
1763         lastTabIndexNodeId_ = nodeIdNeedToFocus;
1764         return true;
1765     }
1766     return false;
1767 }
1768 
GetChildFocusNodeByType(FocusNodeType nodeType)1769 RefPtr<FocusHub> FocusHub::GetChildFocusNodeByType(FocusNodeType nodeType)
1770 {
1771     if (nodeType == FocusNodeType::DEFAULT && IsDefaultFocus() && IsFocusable()) {
1772         return AceType::Claim(this);
1773     }
1774     if (nodeType == FocusNodeType::GROUP_DEFAULT && IsDefaultGroupFocus() && IsFocusable()) {
1775         return AceType::Claim(this);
1776     }
1777     if (focusType_ != FocusType::SCOPE) {
1778         return nullptr;
1779     }
1780     std::list<RefPtr<FocusHub>> focusNodes;
1781     FlushChildrenFocusHub(focusNodes);
1782     for (const auto& child : focusNodes) {
1783         auto findNode = child->GetChildFocusNodeByType(nodeType);
1784         if (findNode) {
1785             return findNode;
1786         }
1787     }
1788     return nullptr;
1789 }
1790 
GetChildFocusNodeById(const std::string & id)1791 RefPtr<FocusHub> FocusHub::GetChildFocusNodeById(const std::string& id)
1792 {
1793     if (id.empty()) {
1794         return nullptr;
1795     }
1796     if (GetInspectorKey().has_value() && GetInspectorKey().value() == id) {
1797         return AceType::Claim(this);
1798     }
1799     if (focusType_ == FocusType::SCOPE) {
1800         std::list<RefPtr<FocusHub>> focusNodes;
1801         FlushChildrenFocusHub(focusNodes);
1802         for (const auto& child : focusNodes) {
1803             auto findNode = child->GetChildFocusNodeById(id);
1804             if (findNode) {
1805                 return findNode;
1806             }
1807         }
1808     }
1809     return nullptr;
1810 }
1811 
HandleParentScroll() const1812 void FocusHub::HandleParentScroll() const
1813 {
1814     auto context = PipelineContext::GetCurrentContext();
1815     CHECK_NULL_VOID(context);
1816     if (!context->GetIsFocusActive() || (focusType_ != FocusType::NODE && !isFocusUnit_)) {
1817         return;
1818     }
1819     auto parent = GetParentFocusHub();
1820     RefPtr<FrameNode> parentFrame;
1821     RefPtr<Pattern> parentPattern;
1822     while (parent) {
1823         if (parent->isFocusUnit_) {
1824             return;
1825         }
1826         parentFrame = parent->GetFrameNode();
1827         if (!parentFrame) {
1828             parent = parent->GetParentFocusHub();
1829             continue;
1830         }
1831         parentPattern = parentFrame->GetPattern();
1832         if (parentPattern && parentPattern->ScrollToNode(GetFrameNode())) {
1833             return;
1834         }
1835         parent = parent->GetParentFocusHub();
1836     }
1837 }
1838 
RequestFocusImmediatelyById(const std::string & id)1839 bool FocusHub::RequestFocusImmediatelyById(const std::string& id)
1840 {
1841     auto focusNode = GetChildFocusNodeById(id);
1842     if (!focusNode) {
1843         TAG_LOGI(AceLogTag::ACE_FOCUS, "Request focus id: %{public}s can not found.", id.c_str());
1844         return false;
1845     }
1846     auto result = true;
1847     if (!focusNode->IsFocusable()) {
1848         result = false;
1849     }
1850     TAG_LOGI(AceLogTag::ACE_FOCUS, "Request focus immediately by id: %{public}s. The node is %{public}s/%{public}d.",
1851         id.c_str(), focusNode->GetFrameName().c_str(), focusNode->GetFrameId());
1852     auto pipeline = PipelineContext::GetCurrentContext();
1853     CHECK_NULL_RETURN(pipeline, false);
1854     pipeline->AddDirtyRequestFocus(focusNode->GetFrameNode());
1855     return result;
1856 }
1857 
GetFocusingTabNodeIdx(TabIndexNodeList & tabIndexNodes) const1858 int32_t FocusHub::GetFocusingTabNodeIdx(TabIndexNodeList& tabIndexNodes) const
1859 {
1860     if (lastTabIndexNodeId_ == DEFAULT_TAB_FOCUSED_INDEX) {
1861         return DEFAULT_TAB_FOCUSED_INDEX;
1862     }
1863     int32_t i = 0;
1864     for (auto& wpNode : tabIndexNodes) {
1865         auto node = wpNode.second.Upgrade();
1866         if (node && node->IsCurrentFocus() && node->GetFrameId() == lastTabIndexNodeId_) {
1867             return i;
1868         }
1869         ++i;
1870     }
1871     return DEFAULT_TAB_FOCUSED_INDEX;
1872 }
1873 
HandleFocusByTabIndex(const KeyEvent & event)1874 bool FocusHub::HandleFocusByTabIndex(const KeyEvent& event)
1875 {
1876     if (event.code != KeyCode::KEY_TAB || event.action != KeyAction::DOWN) {
1877         return false;
1878     }
1879     auto pipeline = PipelineContext::GetCurrentContext();
1880     if (pipeline && pipeline->IsTabJustTriggerOnKeyEvent()) {
1881         return false;
1882     }
1883     TabIndexNodeList tabIndexNodes;
1884     tabIndexNodes.clear();
1885     CollectTabIndexNodes(tabIndexNodes);
1886     if (tabIndexNodes.empty()) {
1887         return false;
1888     }
1889     tabIndexNodes.sort([](std::pair<int32_t, WeakPtr<FocusHub>>& a, std::pair<int32_t, WeakPtr<FocusHub>>& b) {
1890         return a.first < b.first;
1891     });
1892     int32_t curTabFocusIndex = GetFocusingTabNodeIdx(tabIndexNodes);
1893     if ((curTabFocusIndex < 0 || curTabFocusIndex >= static_cast<int32_t>(tabIndexNodes.size())) &&
1894         curTabFocusIndex != DEFAULT_TAB_FOCUSED_INDEX) {
1895         TAG_LOGI(AceLogTag::ACE_FOCUS, "Current focused tabIndex: %{public}d is not valid. Use default focus system.",
1896             curTabFocusIndex);
1897         return false;
1898     }
1899     if (curTabFocusIndex == DEFAULT_TAB_FOCUSED_INDEX) {
1900         curTabFocusIndex = 0;
1901     } else {
1902         if (event.IsShiftWith(KeyCode::KEY_TAB)) {
1903             --curTabFocusIndex;
1904         } else {
1905             ++curTabFocusIndex;
1906         }
1907         if (curTabFocusIndex < 0 || curTabFocusIndex >= static_cast<int32_t>(tabIndexNodes.size())) {
1908             curTabFocusIndex = (curTabFocusIndex + static_cast<int32_t>(tabIndexNodes.size())) %
1909                                static_cast<int32_t>(tabIndexNodes.size());
1910         }
1911     }
1912     return GoToFocusByTabNodeIdx(tabIndexNodes, curTabFocusIndex);
1913 }
1914 
HasBackwardFocusMovementInChildren()1915 bool FocusHub::HasBackwardFocusMovementInChildren()
1916 {
1917     std::list<RefPtr<FocusHub>> children;
1918     FlushChildrenFocusHub(children);
1919     for (const auto& child : children) {
1920         if (child->HasBackwardFocusMovement()) {
1921             return true;
1922         }
1923     }
1924     return false;
1925 }
1926 
HasForwardFocusMovementInChildren()1927 bool FocusHub::HasForwardFocusMovementInChildren()
1928 {
1929     std::list<RefPtr<FocusHub>> children;
1930     FlushChildrenFocusHub(children);
1931     for (const auto& child : children) {
1932         if (child->HasForwardFocusMovement()) {
1933             return true;
1934         }
1935     }
1936     return false;
1937 }
1938 
ClearFocusMovementFlagsInChildren()1939 void FocusHub::ClearFocusMovementFlagsInChildren()
1940 {
1941     std::list<RefPtr<FocusHub>> children;
1942     FlushChildrenFocusHub(children);
1943     for (auto child : children) {
1944         child->ClearFocusMovementFlags();
1945         child->ClearFocusMovementFlagsInChildren();
1946     }
1947 }
1948 
GetProjectAreaOnRect(const RectF & rect,const RectF & projectRect,FocusStep step)1949 double FocusHub::GetProjectAreaOnRect(const RectF& rect, const RectF& projectRect, FocusStep step)
1950 {
1951     float areaWidth = 0.0;
1952     float areaHeight = 0.0;
1953     switch (step) {
1954         case FocusStep::UP:
1955             if (rect.Top() < projectRect.Bottom() && rect.Right() > projectRect.Left() &&
1956                 rect.Left() < projectRect.Right()) {
1957                 areaWidth = std::min(rect.Right(), projectRect.Right()) - std::max(rect.Left(), projectRect.Left());
1958                 areaHeight = std::min(rect.Bottom(), projectRect.Bottom()) - rect.Top();
1959             }
1960             break;
1961         case FocusStep::DOWN:
1962             if (rect.Bottom() > projectRect.Top() && rect.Right() > projectRect.Left() &&
1963                 rect.Left() < projectRect.Right()) {
1964                 areaWidth = std::min(rect.Right(), projectRect.Right()) - std::max(rect.Left(), projectRect.Left());
1965                 areaHeight = rect.Bottom() - std::max(rect.Top(), projectRect.Top());
1966             }
1967             break;
1968         case FocusStep::LEFT:
1969             if (rect.Left() < projectRect.Right() && rect.Bottom() > projectRect.Top() &&
1970                 rect.Top() < projectRect.Bottom()) {
1971                 areaWidth = std::min(rect.Right(), projectRect.Right()) - rect.Left();
1972                 areaHeight = std::min(rect.Bottom(), projectRect.Bottom()) - std::max(rect.Top(), projectRect.Top());
1973             }
1974             break;
1975         case FocusStep::RIGHT:
1976             if (rect.Right() > projectRect.Left() && rect.Bottom() > projectRect.Top() &&
1977                 rect.Top() < projectRect.Bottom()) {
1978                 areaWidth = rect.Right() - std::max(rect.Left(), projectRect.Left());
1979                 areaHeight = std::min(rect.Bottom(), projectRect.Bottom()) - std::max(rect.Top(), projectRect.Top());
1980             }
1981             break;
1982         default:
1983             break;
1984     }
1985     return areaWidth * areaHeight;
1986 }
1987 
GetNearestNodeByProjectArea(const std::list<RefPtr<FocusHub>> & allNodes,FocusStep step)1988 RefPtr<FocusHub> FocusHub::GetNearestNodeByProjectArea(const std::list<RefPtr<FocusHub>>& allNodes, FocusStep step)
1989 {
1990     CHECK_NULL_RETURN(!allNodes.empty(), nullptr);
1991     auto curFrameNode = GetFrameNode();
1992     CHECK_NULL_RETURN(curFrameNode, nullptr);
1993     auto curFrameOffset = curFrameNode->GetOffsetRelativeToWindow();
1994     auto curGeometryNode = curFrameNode->GetGeometryNode();
1995     CHECK_NULL_RETURN(curGeometryNode, nullptr);
1996     RectF curFrameRect = RectF(curFrameOffset, curGeometryNode->GetFrameRect().GetSize());
1997     curFrameRect.SetOffset(curFrameOffset);
1998     TAG_LOGD(AceLogTag::ACE_FOCUS,
1999         "Current focus node is %{public}s/%{public}d. Rect is {%{public}f,%{public}f,%{public}f,%{public}f}.",
2000         GetFrameName().c_str(), GetFrameId(), curFrameRect.Left(), curFrameRect.Top(), curFrameRect.Right(),
2001         curFrameRect.Bottom());
2002     bool isTabStep = IsFocusStepTab(step);
2003     double resDistance = !isTabStep ? std::numeric_limits<double>::max() : 0.0f;
2004     RefPtr<FocusHub> nextNode;
2005     for (const auto& node : allNodes) {
2006         if (!node || AceType::RawPtr(node) == this) {
2007             continue;
2008         }
2009         auto frameNode = node->GetFrameNode();
2010         if (!frameNode) {
2011             continue;
2012         }
2013         auto frameOffset = frameNode->GetOffsetRelativeToWindow();
2014         auto geometryNode = frameNode->GetGeometryNode();
2015         if (!geometryNode) {
2016             continue;
2017         }
2018         RectF frameRect = RectF(frameOffset, geometryNode->GetFrameRect().GetSize());
2019         auto realStep = step;
2020         if (step == FocusStep::TAB) {
2021             frameRect -= OffsetF(0, curFrameRect.Height());
2022             realStep = FocusStep::LEFT;
2023         } else if (step == FocusStep::SHIFT_TAB) {
2024             frameRect += OffsetF(0, curFrameRect.Height());
2025             realStep = FocusStep::RIGHT;
2026         }
2027         auto projectArea = GetProjectAreaOnRect(frameRect, curFrameRect, realStep);
2028         if (Positive(projectArea)) {
2029             OffsetF vec = frameRect.Center() - curFrameRect.Center();
2030             double val = (vec.GetX() * vec.GetX()) + (vec.GetY() * vec.GetY());
2031             if ((step == FocusStep::TAB && Positive(vec.GetX())) ||
2032                 (step == FocusStep::SHIFT_TAB && Negative(vec.GetX()))) {
2033                 val *= -1.0;
2034             }
2035             if ((!isTabStep && val < resDistance) || (isTabStep && val > resDistance)) {
2036                 resDistance = val;
2037                 nextNode = node;
2038             }
2039         }
2040     }
2041     TAG_LOGD(AceLogTag::ACE_FOCUS, "Next focus node is %{public}s/%{public}d. Min distance is %{public}f.",
2042         nextNode ? nextNode->GetFrameName().c_str() : "NULL", nextNode ? nextNode->GetFrameId() : -1, resDistance);
2043     return nextNode;
2044 }
2045 
CloseKeyboard()2046 void FocusHub::CloseKeyboard()
2047 {
2048 #if defined(ENABLE_STANDARD_INPUT)
2049     TAG_LOGI(AceLogTag::ACE_KEYBOARD, "CloseKeyBoard");
2050     auto inputMethod = MiscServices::InputMethodController::GetInstance();
2051     if (inputMethod) {
2052         inputMethod->Close();
2053         TAG_LOGI(AceLogTag::ACE_KEYBOARD, "CloseKeyBoard SoftKeyboard Closes Successfully.");
2054     }
2055 #endif
2056 }
2057 } // namespace OHOS::Ace::NG
2058