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