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