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