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