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