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