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
20 #include "base/geometry/ng/offset_t.h"
21 #include "base/geometry/ng/rect_t.h"
22 #include "base/log/dump_log.h"
23 #include "base/utils/utils.h"
24 #include "core/common/ace_application_info.h"
25 #include "core/components/theme/app_theme.h"
26 #include "core/components_ng/base/frame_node.h"
27 #include "core/components_ng/base/geometry_node.h"
28 #include "core/components_ng/event/gesture_event_hub.h"
29 #include "core/components_v2/inspector/inspector_constants.h"
30 #include "core/event/ace_event_handler.h"
31 #include "core/pipeline_ng/pipeline_context.h"
32
33 #ifdef WINDOW_SCENE_SUPPORTED
34 #include "core/components_ng/pattern/window_scene/helper/window_scene_helper.h"
35 #endif
36
37 #if not defined(ACE_UNITTEST)
38 #if defined(ENABLE_STANDARD_INPUT)
39 #include "core/components_ng/pattern/text_field/on_text_changed_listener_impl.h"
40 #endif
41 #endif
42
43 namespace OHOS::Ace::NG {
44
GetFrameNode() const45 RefPtr<FrameNode> FocusHub::GetFrameNode() const
46 {
47 auto eventHub = eventHub_.Upgrade();
48 return eventHub ? eventHub->GetFrameNode() : nullptr;
49 }
50
GetGeometryNode() const51 RefPtr<GeometryNode> FocusHub::GetGeometryNode() const
52 {
53 auto frameNode = GetFrameNode();
54 return frameNode ? frameNode->GetGeometryNode() : nullptr;
55 }
56
GetInspectorKey() const57 std::optional<std::string> FocusHub::GetInspectorKey() const
58 {
59 auto frameNode = GetFrameNode();
60 CHECK_NULL_RETURN(frameNode, std::nullopt);
61 return frameNode->GetInspectorId();
62 }
63
GetParentFocusHub() const64 RefPtr<FocusHub> FocusHub::GetParentFocusHub() const
65 {
66 auto frameNode = GetFrameNode();
67 CHECK_NULL_RETURN(frameNode, nullptr);
68 auto parentNode = frameNode->GetFocusParent();
69 return parentNode ? parentNode->GetFocusHub() : nullptr;
70 }
71
GetRootFocusHub()72 RefPtr<FocusHub> FocusHub::GetRootFocusHub()
73 {
74 RefPtr<FocusHub> parent = AceType::Claim(this);
75 while (parent->GetParentFocusHub()) {
76 parent = parent->GetParentFocusHub();
77 }
78 return parent;
79 }
80
GetFrameName() const81 std::string FocusHub::GetFrameName() const
82 {
83 auto frameNode = GetFrameNode();
84 return frameNode ? frameNode->GetTag() : "NULL";
85 }
86
GetFrameId() const87 int32_t FocusHub::GetFrameId() const
88 {
89 auto frameNode = GetFrameNode();
90 return frameNode ? frameNode->GetId() : -1;
91 }
92
FlushChildrenFocusHub(std::list<RefPtr<FocusHub>> & focusNodes)93 std::list<RefPtr<FocusHub>>::iterator FocusHub::FlushChildrenFocusHub(std::list<RefPtr<FocusHub>>& focusNodes)
94 {
95 focusNodes.clear();
96 std::list<RefPtr<FrameNode>> childrenNode;
97 auto frameNode = GetFrameNode();
98 if (frameNode) {
99 frameNode->GetFocusChildren(childrenNode);
100 }
101 for (const auto& child : childrenNode) {
102 if (child->GetFocusHub()) {
103 focusNodes.emplace_back(child->GetFocusHub());
104 }
105 }
106 auto lastFocusNode = lastWeakFocusNode_.Upgrade();
107 if (!lastFocusNode) {
108 return focusNodes.end();
109 }
110 return std::find(focusNodes.begin(), focusNodes.end(), lastFocusNode);
111 }
112
HandleKeyEvent(const KeyEvent & keyEvent)113 bool FocusHub::HandleKeyEvent(const KeyEvent& keyEvent)
114 {
115 if (!IsCurrentFocus()) {
116 return false;
117 }
118 bool shiftTabPressed = keyEvent.IsShiftWith(KeyCode::KEY_TAB);
119 bool leftArrowPressed = keyEvent.code == KeyCode::KEY_DPAD_LEFT;
120 hasBackwardMovement_ = keyEvent.action == KeyAction::DOWN && (shiftTabPressed || leftArrowPressed);
121
122 bool tabOnlyPressed = (keyEvent.code == KeyCode::KEY_TAB) && (!shiftTabPressed);
123 bool rightArrowPressed = keyEvent.code == KeyCode::KEY_DPAD_RIGHT;
124 hasForwardMovement_ = keyEvent.action == KeyAction::DOWN && (tabOnlyPressed || rightArrowPressed);
125
126 return OnKeyEvent(keyEvent);
127 }
128
DumpFocusTree(int32_t depth)129 void FocusHub::DumpFocusTree(int32_t depth)
130 {
131 if (focusType_ == FocusType::NODE) {
132 DumpFocusNodeTree(depth);
133 } else if (focusType_ == FocusType::SCOPE) {
134 DumpFocusScopeTree(depth);
135 }
136 }
137
DumpFocusNodeTree(int32_t depth)138 void FocusHub::DumpFocusNodeTree(int32_t depth)
139 {
140 if (DumpLog::GetInstance().GetDumpFile()) {
141 std::string information = GetFrameName();
142 if (IsCurrentFocus()) {
143 information += "(Node*)";
144 } else {
145 information += "(Node)";
146 }
147 information += (" id:" + std::to_string(GetFrameId()));
148 if (!IsFocusable()) {
149 information = "(-)" + information;
150 information += (" Enabled:" + std::to_string(IsEnabled()) + " Show:" + std::to_string(IsShow()) +
151 " Focusable:" + std::to_string(focusable_) +
152 " ParentFocusable:" + std::to_string(parentFocusable_));
153 }
154 DumpLog::GetInstance().Print(depth, information, 0);
155 }
156 }
157
DumpFocusScopeTree(int32_t depth)158 void FocusHub::DumpFocusScopeTree(int32_t depth)
159 {
160 std::list<RefPtr<FocusHub>> focusNodes;
161 FlushChildrenFocusHub(focusNodes);
162 if (DumpLog::GetInstance().GetDumpFile()) {
163 std::string information = GetFrameName();
164 if (IsCurrentFocus()) {
165 information += "(Scope*)";
166 } else {
167 information += "(Scope)";
168 }
169 information += (" id:" + std::to_string(GetFrameId()));
170 if (!IsFocusable()) {
171 information = "(-)" + information;
172 if (!IsFocusableNode()) {
173 information += (" Enabled:" + std::to_string(IsEnabled()) + " Show:" + std::to_string(IsShow()) +
174 " Focusable:" + std::to_string(focusable_) +
175 " ParentFocusable:" + std::to_string(parentFocusable_));
176 }
177 }
178 DumpLog::GetInstance().Print(depth, information, static_cast<int32_t>(focusNodes.size()));
179 }
180
181 for (const auto& item : focusNodes) {
182 item->DumpFocusTree(depth + 1);
183 }
184 }
185
RequestFocusImmediately(bool isJudgeRootTree)186 bool FocusHub::RequestFocusImmediately(bool isJudgeRootTree)
187 {
188 auto context = NG::PipelineContext::GetCurrentContext();
189 if (context && context->GetIsFocusingByTab()) {
190 if (!IsFocusableByTab()) {
191 return false;
192 }
193 }
194
195 if (IsCurrentFocus()) {
196 return true;
197 }
198
199 if (!IsFocusableWholePath()) {
200 return false;
201 }
202
203 if (isJudgeRootTree && !IsOnRootTree()) {
204 return false;
205 }
206
207 currentFocus_ = true;
208 UpdateAccessibilityFocusInfo();
209
210 if (onPreFocusCallback_) {
211 onPreFocusCallback_();
212 }
213
214 auto parent = GetParentFocusHub();
215 if (parent) {
216 auto mainView = GetCurrentMainView();
217 auto mainViewRootScope = mainView ? mainView->GetMainViewRootScope() : nullptr;
218 if (mainViewRootScope && parent == mainViewRootScope) {
219 mainView->SetIsViewRootScopeFocused(mainViewRootScope, false);
220 }
221 parent->SwitchFocus(AceType::Claim(this));
222 }
223
224 HandleFocus();
225 return true;
226 }
227
UpdateAccessibilityFocusInfo()228 void FocusHub::UpdateAccessibilityFocusInfo()
229 {
230 // Need update
231 }
232
GetChildMainView()233 RefPtr<FocusHub> FocusHub::GetChildMainView()
234 {
235 std::list<RefPtr<FocusHub>> children;
236 FlushChildrenFocusHub(children);
237 RefPtr<FocusHub> curFocusMainView = nullptr;
238 RefPtr<FocusHub> focusableMainView = nullptr;
239 for (const auto& child : children) {
240 if (!child) {
241 continue;
242 }
243 auto frameName = child->GetFrameName();
244 if (frameName == V2::PAGE_ETS_TAG || frameName == V2::DIALOG_ETS_TAG || frameName == V2::MODAL_PAGE_TAG ||
245 frameName == V2::MENU_ETS_TAG || frameName == V2::SHEET_PAGE_TAG || frameName == V2::POPUP_ETS_TAG ||
246 frameName == V2::WINDOW_SCENE_ETS_TAG) {
247 if (!curFocusMainView && child->IsCurrentFocus() && child->IsFocusable()) {
248 curFocusMainView = child;
249 }
250 if (!focusableMainView && child->IsFocusable()) {
251 focusableMainView = child;
252 }
253 }
254 }
255 if (curFocusMainView) {
256 return curFocusMainView;
257 }
258 if (focusableMainView) {
259 return focusableMainView;
260 }
261 for (const auto& child : children) {
262 if (!child) {
263 continue;
264 }
265 auto result = child->GetChildMainView();
266 if (result) {
267 return result;
268 }
269 }
270 return nullptr;
271 }
272
GetCurrentMainView()273 RefPtr<FocusHub> FocusHub::GetCurrentMainView()
274 {
275 auto pipeline = PipelineContext::GetCurrentContext();
276 CHECK_NULL_RETURN(pipeline, nullptr);
277 auto screenNode = pipeline->GetScreenNode();
278 if (screenNode) {
279 auto screenNodeFocusHub = screenNode->GetFocusHub();
280 CHECK_NULL_RETURN(screenNodeFocusHub, nullptr);
281 return screenNodeFocusHub->GetChildMainView();
282 }
283 auto rootNode = pipeline->GetRootElement();
284 CHECK_NULL_RETURN(rootNode, nullptr);
285 auto rootFocusHub = rootNode->GetFocusHub();
286 CHECK_NULL_RETURN(rootFocusHub, nullptr);
287 return rootFocusHub->GetChildMainView();
288 }
289
GetMainViewRootScope()290 RefPtr<FocusHub> FocusHub::GetMainViewRootScope()
291 {
292 static const std::list<int32_t> DEEPTH_OF_MENU = { 0, 0 };
293 static const std::list<int32_t> DEEPTH_OF_DIALOG = { 0, 0 };
294 static const std::list<int32_t> DEEPTH_OF_PAGE = { 0 };
295 static const std::list<int32_t> DEEPTH_OF_POPUP = { 0, 0 };
296 static const std::list<int32_t> DEEPTH_OF_SHEET_PAGE = { 1, 0 };
297 auto frameName = GetFrameName();
298 std::list<int32_t> rootScopeDeepth;
299 if (frameName == V2::MENU_ETS_TAG) {
300 rootScopeDeepth = DEEPTH_OF_MENU;
301 } else if (frameName == V2::DIALOG_ETS_TAG) {
302 rootScopeDeepth = DEEPTH_OF_DIALOG;
303 } else if (frameName == V2::POPUP_ETS_TAG) {
304 rootScopeDeepth = DEEPTH_OF_POPUP;
305 } else if (frameName == V2::SHEET_PAGE_TAG) {
306 rootScopeDeepth = DEEPTH_OF_SHEET_PAGE;
307 } else {
308 rootScopeDeepth = DEEPTH_OF_PAGE;
309 }
310 RefPtr<FocusHub> rootScope = AceType::Claim(this);
311 for (const auto& index : rootScopeDeepth) {
312 CHECK_NULL_RETURN(rootScope, nullptr);
313 auto children = rootScope->GetChildren();
314 auto iter = children.begin();
315 std::advance(iter, index);
316 if (iter == children.end()) {
317 TAG_LOGI(AceLogTag::ACE_FOCUS, "Index: %{public}d of %{public}s/%{public}d 's children is invalid.", index,
318 rootScope->GetFrameName().c_str(), rootScope->GetFrameId());
319 return nullptr;
320 }
321 rootScope = *iter;
322 }
323 CHECK_NULL_RETURN(rootScope, nullptr);
324 if (rootScope->GetFocusType() != FocusType::SCOPE) {
325 return rootScope->GetParentFocusHub();
326 }
327 return rootScope;
328 }
329
LostFocusToViewRoot()330 void FocusHub::LostFocusToViewRoot()
331 {
332 auto mainView = GetCurrentMainView();
333 CHECK_NULL_VOID(mainView);
334 auto mainViewRootScope = mainView->GetMainViewRootScope();
335 CHECK_NULL_VOID(mainViewRootScope);
336 TAG_LOGD(AceLogTag::ACE_FOCUS, "Lost focus to view root: %{public}s/%{public}d",
337 mainViewRootScope->GetFrameName().c_str(), mainViewRootScope->GetFrameId());
338 if (!mainViewRootScope->IsCurrentFocus()) {
339 TAG_LOGI(AceLogTag::ACE_FOCUS, "View root: %{public}s/%{public}d is not on focusing.",
340 mainViewRootScope->GetFrameName().c_str(), mainViewRootScope->GetFrameId());
341 return;
342 }
343 mainView->SetIsViewRootScopeFocused(mainViewRootScope, true);
344 auto focusedChild = mainViewRootScope->lastWeakFocusNode_.Upgrade();
345 CHECK_NULL_VOID(focusedChild);
346 focusedChild->LostFocus();
347 }
348
HandleFocusOnMainView()349 bool FocusHub::HandleFocusOnMainView()
350 {
351 auto viewRootScope = GetMainViewRootScope();
352 CHECK_NULL_RETURN(viewRootScope, false);
353 if (!viewRootScope->IsCurrentFocus()) {
354 TAG_LOGI(AceLogTag::ACE_FOCUS,
355 "Current view root: %{public}s/%{public}d is not on focusing. Cannot handle focus.",
356 viewRootScope->GetFrameName().c_str(), viewRootScope->GetFrameId());
357 return false;
358 }
359 if (viewRootScope->GetFocusDependence() != FocusDependence::SELF) {
360 TAG_LOGI(AceLogTag::ACE_FOCUS,
361 "Current view root: %{public}s/%{public}d is not focus depend self. Do not need handle focus.",
362 viewRootScope->GetFrameName().c_str(), viewRootScope->GetFrameId());
363 return false;
364 }
365
366 TabIndexNodeList tabIndexNodes;
367 tabIndexNodes.clear();
368 CollectTabIndexNodes(tabIndexNodes);
369 if (tabIndexNodes.empty()) {
370 // No tabIndex node in current main view. Extend focus from viewRootScope to children.
371 SetIsDefaultHasFocused(true);
372 SetIsViewRootScopeFocused(viewRootScope, false);
373 viewRootScope->OnFocusScope(true);
374 return true;
375 }
376
377 // First tabIndex node need get focus.
378 tabIndexNodes.sort([](std::pair<int32_t, WeakPtr<FocusHub>>& a, std::pair<int32_t, WeakPtr<FocusHub>>& b) {
379 return a.first < b.first;
380 });
381 return GoToFocusByTabNodeIdx(tabIndexNodes, 0);
382 }
383
LostFocus(BlurReason reason)384 void FocusHub::LostFocus(BlurReason reason)
385 {
386 TAG_LOGD(AceLogTag::ACE_FOCUS, "Node %{public}s/%{public}d lost focus. Lost reason: %{public}d.",
387 GetFrameName().c_str(), GetFrameId(), reason);
388 if (IsCurrentFocus()) {
389 blurReason_ = reason;
390 currentFocus_ = false;
391 UpdateAccessibilityFocusInfo();
392 OnBlur();
393 }
394 }
395
LostSelfFocus()396 void FocusHub::LostSelfFocus()
397 {
398 if (IsCurrentFocus()) {
399 SetFocusable(false);
400 SetFocusable(true);
401 }
402 }
403
RemoveSelf(BlurReason reason)404 void FocusHub::RemoveSelf(BlurReason reason)
405 {
406 TAG_LOGD(AceLogTag::ACE_FOCUS, "Node %{public}s/%{public}d remove self.", GetFrameName().c_str(), GetFrameId());
407 auto pipeline = PipelineContext::GetCurrentContext();
408 auto screenNode = pipeline ? pipeline->GetScreenNode() : nullptr;
409 auto screenFocusHub = screenNode ? screenNode->GetFocusHub() : nullptr;
410 auto parent = GetParentFocusHub();
411 if (parent && parent != screenFocusHub) {
412 parent->RemoveChild(AceType::Claim(this), reason);
413 } else {
414 LostFocus(reason);
415 }
416 }
417
RemoveChild(const RefPtr<FocusHub> & focusNode,BlurReason reason)418 void FocusHub::RemoveChild(const RefPtr<FocusHub>& focusNode, BlurReason reason)
419 {
420 // Not belong to this focus scope.
421 if (!focusNode || focusNode->GetParentFocusHub() != this) {
422 return;
423 }
424
425 std::list<RefPtr<FocusHub>> focusNodes;
426 auto itLastFocusNode = FlushChildrenFocusHub(focusNodes);
427
428 if (focusNode->IsCurrentFocus()) {
429 // Try to goto next focus, otherwise goto previous focus.
430 if (!GoToNextFocusLinear(FocusStep::TAB) && !GoToNextFocusLinear(FocusStep::SHIFT_TAB)) {
431 lastWeakFocusNode_ = nullptr;
432 auto mainView = GetCurrentMainView();
433 auto mainViewRootScope = mainView ? mainView->GetMainViewRootScope() : nullptr;
434 if (mainViewRootScope && mainViewRootScope == AceType::Claim(this)) {
435 mainView->SetIsViewRootScopeFocused(mainViewRootScope, true);
436 } else {
437 RemoveSelf(reason);
438 }
439 }
440 focusNode->LostFocus(reason);
441 } else {
442 if (itLastFocusNode != focusNodes.end() && (*itLastFocusNode) == focusNode) {
443 lastWeakFocusNode_ = nullptr;
444 }
445 }
446
447 auto it = std::find(focusNodes.begin(), focusNodes.end(), focusNode);
448 if (it == focusNodes.end()) {
449 return;
450 }
451 auto lastFocusNode = lastWeakFocusNode_.Upgrade();
452 if (lastFocusNode == focusNode) {
453 lastWeakFocusNode_ = nullptr;
454 }
455 }
456
457 // Need update RebuildChild function
458
SetParentFocusable(bool parentFocusable)459 void FocusHub::SetParentFocusable(bool parentFocusable)
460 {
461 parentFocusable_ = parentFocusable;
462 }
463
IsFocusable()464 bool FocusHub::IsFocusable()
465 {
466 if (focusType_ == FocusType::NODE) {
467 return IsFocusableNode();
468 }
469 if (focusType_ == FocusType::SCOPE) {
470 return IsFocusableScope();
471 }
472 return false;
473 }
474
IsFocusableScope()475 bool FocusHub::IsFocusableScope()
476 {
477 if (!IsFocusableNode()) {
478 return false;
479 }
480 if (focusDepend_ == FocusDependence::SELF || focusDepend_ == FocusDependence::AUTO) {
481 return true;
482 }
483 std::list<RefPtr<FocusHub>> focusNodes;
484 FlushChildrenFocusHub(focusNodes);
485 return std::any_of(focusNodes.begin(), focusNodes.end(),
486 [](const RefPtr<FocusHub>& focusNode) { return focusNode->IsFocusable(); });
487 }
488
IsFocusableNode()489 bool FocusHub::IsFocusableNode()
490 {
491 return IsEnabled() && IsShow() && focusable_ && parentFocusable_;
492 }
493
SetFocusable(bool focusable,bool isExplicit)494 void FocusHub::SetFocusable(bool focusable, bool isExplicit)
495 {
496 if (isExplicit) {
497 isFocusableExplicit_ = true;
498 } else if (isFocusableExplicit_) {
499 LOGI("Current focusHub cannot be set to focusable implicitly.");
500 return;
501 } else {
502 implicitFocusable_ = focusable;
503 }
504 if (IsImplicitFocusableScope() && focusDepend_ == FocusDependence::CHILD) {
505 focusDepend_ = FocusDependence::AUTO;
506 }
507
508 if (focusable_ == focusable) {
509 return;
510 }
511 focusable_ = focusable;
512 if (!focusable) {
513 RemoveSelf(BlurReason::FOCUS_SWITCH);
514 }
515 }
516
IsEnabled() const517 bool FocusHub::IsEnabled() const
518 {
519 auto eventHub = eventHub_.Upgrade();
520 return eventHub ? eventHub->IsEnabled() : true;
521 }
522
SetEnabled(bool enabled)523 void FocusHub::SetEnabled(bool enabled)
524 {
525 if (!enabled) {
526 RemoveSelf(BlurReason::FOCUS_SWITCH);
527 }
528 }
529
IsShow() const530 bool FocusHub::IsShow() const
531 {
532 auto frameNode = GetFrameNode();
533 CHECK_NULL_RETURN(frameNode, true);
534 bool curIsVisible = frameNode->IsVisible();
535 auto parent = frameNode->GetParent();
536 while (parent) {
537 auto parentFrame = AceType::DynamicCast<FrameNode>(parent);
538 if (parentFrame && !parentFrame->IsVisible()) {
539 curIsVisible = false;
540 break;
541 }
542 parent = parent->GetParent();
543 }
544 return curIsVisible;
545 }
546
SetShow(bool show)547 void FocusHub::SetShow(bool show)
548 {
549 if (!show) {
550 RemoveSelf(BlurReason::FOCUS_SWITCH);
551 }
552 }
553
IsCurrentFocusWholePath()554 bool FocusHub::IsCurrentFocusWholePath()
555 {
556 if (!currentFocus_) {
557 return false;
558 }
559 if (focusType_ == FocusType::NODE) {
560 return true;
561 }
562 if (focusType_ == FocusType::SCOPE) {
563 if (focusDepend_ == FocusDependence::SELF || focusDepend_ == FocusDependence::AUTO) {
564 return true;
565 }
566 std::list<RefPtr<FocusHub>> focusNodes;
567 auto itLastFocusNode = FlushChildrenFocusHub(focusNodes);
568 if (itLastFocusNode == focusNodes.end() || !(*itLastFocusNode)) {
569 return false;
570 }
571 return (*itLastFocusNode)->IsCurrentFocusWholePath();
572 }
573 return false;
574 }
575
SetIsFocusOnTouch(bool isFocusOnTouch)576 void FocusHub::SetIsFocusOnTouch(bool isFocusOnTouch)
577 {
578 if (!focusCallbackEvents_) {
579 focusCallbackEvents_ = MakeRefPtr<FocusCallbackEvents>();
580 }
581 if (focusCallbackEvents_->IsFocusOnTouch().has_value() &&
582 focusCallbackEvents_->IsFocusOnTouch().value() == isFocusOnTouch) {
583 return;
584 }
585 focusCallbackEvents_->SetIsFocusOnTouch(isFocusOnTouch);
586
587 auto frameNode = GetFrameNode();
588 CHECK_NULL_VOID(frameNode);
589 auto gesture = frameNode->GetOrCreateGestureEventHub();
590 CHECK_NULL_VOID(gesture);
591
592 if (!isFocusOnTouch && !focusOnTouchListener_) {
593 return;
594 }
595 if (!isFocusOnTouch && focusOnTouchListener_) {
596 gesture->RemoveTouchEvent(focusOnTouchListener_);
597 return;
598 }
599 if (!focusOnTouchListener_) {
600 auto touchCallback = [weak = WeakClaim(this)](const TouchEventInfo& info) {
601 auto focusHub = weak.Upgrade();
602 if (focusHub && info.GetTouches().front().GetTouchType() == TouchType::UP) {
603 focusHub->RequestFocusImmediately();
604 }
605 };
606 focusOnTouchListener_ = MakeRefPtr<TouchEventImpl>(std::move(touchCallback));
607 }
608 gesture->AddTouchEvent(focusOnTouchListener_);
609 }
610
SetIsDefaultFocus(bool isDefaultFocus)611 void FocusHub::SetIsDefaultFocus(bool isDefaultFocus)
612 {
613 if (!focusCallbackEvents_) {
614 focusCallbackEvents_ = MakeRefPtr<FocusCallbackEvents>();
615 }
616 focusCallbackEvents_->SetIsDefaultFocus(isDefaultFocus);
617 }
SetIsDefaultGroupFocus(bool isDefaultGroupFocus)618 void FocusHub::SetIsDefaultGroupFocus(bool isDefaultGroupFocus)
619 {
620 if (!focusCallbackEvents_) {
621 focusCallbackEvents_ = MakeRefPtr<FocusCallbackEvents>();
622 }
623 focusCallbackEvents_->SetIsDefaultGroupFocus(isDefaultGroupFocus);
624 }
625
RefreshFocus()626 void FocusHub::RefreshFocus()
627 {
628 if (!IsCurrentFocus()) {
629 return;
630 }
631
632 // lost current focus and request another focus
633 auto parent = GetParentFocusHub();
634
635 // current node is root node
636 if (!parent) {
637 LostFocus();
638 return;
639 }
640 while (!parent->IsFocusable()) {
641 // parent node is root node
642 if (!parent->GetParentFocusHub()) {
643 parent->LostFocus();
644 return;
645 }
646 parent = parent->GetParentFocusHub();
647 }
648 parent->LostFocus();
649 parent->RequestFocusImmediately();
650 }
651
OnKeyEvent(const KeyEvent & keyEvent)652 bool FocusHub::OnKeyEvent(const KeyEvent& keyEvent)
653 {
654 if (focusType_ == FocusType::SCOPE) {
655 return OnKeyEventScope(keyEvent);
656 }
657 if (focusType_ == FocusType::NODE) {
658 return OnKeyEventNode(keyEvent);
659 }
660 TAG_LOGW(AceLogTag::ACE_FOCUS, "Current node focus type: %{public}d is invalid.", focusType_);
661 return false;
662 }
663
OnKeyEventNode(const KeyEvent & keyEvent)664 bool FocusHub::OnKeyEventNode(const KeyEvent& keyEvent)
665 {
666 ACE_DCHECK(IsCurrentFocus());
667
668 auto retInternal = false;
669 auto pipeline = PipelineContext::GetCurrentContext();
670 bool isBypassInner = keyEvent.IsKey({ KeyCode::KEY_TAB }) && pipeline && pipeline->IsTabJustTriggerOnKeyEvent();
671 if (!isBypassInner && !onKeyEventsInternal_.empty()) {
672 retInternal = ProcessOnKeyEventInternal(keyEvent);
673 TAG_LOGI(AceLogTag::ACE_FOCUS,
674 "OnKeyEventInteral: Node %{public}s/%{public}d handle KeyEvent(%{public}d, %{public}d) return: %{public}d",
675 GetFrameName().c_str(), GetFrameId(), keyEvent.code, keyEvent.action, retInternal);
676 }
677
678 auto info = KeyEventInfo(keyEvent);
679 if (pipeline &&
680 (pipeline->IsKeyInPressed(KeyCode::KEY_META_LEFT) || pipeline->IsKeyInPressed(KeyCode::KEY_META_RIGHT))) {
681 info.SetMetaKey(1);
682 }
683 auto retCallback = false;
684 auto onKeyEventCallback = GetOnKeyCallback();
685 if (onKeyEventCallback) {
686 onKeyEventCallback(info);
687 retCallback = info.IsStopPropagation();
688 TAG_LOGI(AceLogTag::ACE_FOCUS,
689 "OnKeyEventUser: Node %{public}s/%{public}d handle KeyEvent(%{public}d, %{public}d) return: %{public}d",
690 GetFrameName().c_str(), GetFrameId(), keyEvent.code, keyEvent.action, retCallback);
691 }
692
693 if (!retInternal && !retCallback && keyEvent.action == KeyAction::DOWN) {
694 auto ret = false;
695 switch (keyEvent.code) {
696 case KeyCode::KEY_SPACE:
697 case KeyCode::KEY_ENTER:
698 case KeyCode::KEY_NUMPAD_ENTER:
699 ret = OnClick(keyEvent);
700 TAG_LOGI(AceLogTag::ACE_FOCUS,
701 "OnClick: Node %{public}s/%{public}d handle KeyEvent(%{public}d, %{public}d) return: %{public}d",
702 GetFrameName().c_str(), GetFrameId(), keyEvent.code, keyEvent.action, ret);
703 break;
704 default:;
705 }
706 return ret;
707 }
708 return retInternal || retCallback;
709 }
710
OnKeyEventScope(const KeyEvent & keyEvent)711 bool FocusHub::OnKeyEventScope(const KeyEvent& keyEvent)
712 {
713 ACE_DCHECK(IsCurrentFocus());
714 std::list<RefPtr<FocusHub>> focusNodes;
715 auto lastFocusNode = lastWeakFocusNode_.Upgrade();
716 if (lastFocusNode && lastFocusNode->HandleKeyEvent(keyEvent)) {
717 TAG_LOGD(AceLogTag::ACE_FOCUS,
718 "OnKeyEvent: Node %{public}s/%{public}d will not handle KeyEvent(code:%{public}d, action:%{public}d). "
719 "Because its child %{public}s/%{public}d already has consumed this event.",
720 GetFrameName().c_str(), GetFrameId(), keyEvent.code, keyEvent.action, lastFocusNode->GetFrameName().c_str(),
721 lastFocusNode->GetFrameId());
722 return true;
723 }
724
725 if (OnKeyEventNode(keyEvent)) {
726 return true;
727 }
728
729 if (keyEvent.action != KeyAction::DOWN) {
730 return false;
731 }
732
733 auto pipeline = PipelineContext::GetCurrentContext();
734 CHECK_NULL_RETURN(pipeline, false);
735 if (!pipeline->GetIsFocusActive()) {
736 return false;
737 }
738 if (keyEvent.IsKey({ KeyCode::KEY_TAB }) && pipeline->IsTabJustTriggerOnKeyEvent()) {
739 ScrollToLastFocusIndex();
740 return false;
741 }
742
743 ScrollToLastFocusIndex();
744 if (!CalculatePosition()) {
745 return false;
746 }
747
748 switch (keyEvent.code) {
749 case KeyCode::TV_CONTROL_UP:
750 return RequestNextFocus(FocusStep::UP, GetRect());
751 case KeyCode::TV_CONTROL_DOWN:
752 return RequestNextFocus(FocusStep::DOWN, GetRect());
753 case KeyCode::TV_CONTROL_LEFT:
754 return RequestNextFocus(FocusStep::LEFT, GetRect());
755 case KeyCode::TV_CONTROL_RIGHT:
756 return RequestNextFocus(FocusStep::RIGHT, GetRect());
757 case KeyCode::KEY_TAB: {
758 auto context = NG::PipelineContext::GetCurrentContext();
759 bool ret = false;
760 if (keyEvent.pressedCodes.size() == 1) {
761 context->SetIsFocusingByTab(true);
762 ret = RequestNextFocus(FocusStep::TAB, GetRect());
763 auto focusParent = GetParentFocusHub();
764 if (!focusParent || !focusParent->IsCurrentFocus()) {
765 if (context->IsFocusWindowIdSetted()) {
766 FocusToHeadOrTailChild(true);
767 return false;
768 }
769 ret = FocusToHeadOrTailChild(true);
770 }
771 context->SetIsFocusingByTab(false);
772 } else if (keyEvent.IsShiftWith(KeyCode::KEY_TAB)) {
773 context->SetIsFocusingByTab(true);
774 ret = RequestNextFocus(FocusStep::SHIFT_TAB, GetRect());
775 auto focusParent = GetParentFocusHub();
776 if (!focusParent || !focusParent->IsCurrentFocus()) {
777 if (context->IsFocusWindowIdSetted()) {
778 FocusToHeadOrTailChild(false);
779 return false;
780 }
781 ret = FocusToHeadOrTailChild(false);
782 }
783 context->SetIsFocusingByTab(false);
784 }
785 return ret;
786 }
787 case KeyCode::KEY_MOVE_HOME:
788 return RequestNextFocus(FocusStep::LEFT_END, GetRect()) || RequestNextFocus(FocusStep::UP_END, GetRect());
789 case KeyCode::KEY_MOVE_END:
790 return RequestNextFocus(FocusStep::RIGHT_END, GetRect()) ||
791 RequestNextFocus(FocusStep::DOWN_END, GetRect());
792 default:
793 return false;
794 }
795 }
796
RequestFocus() const797 void FocusHub::RequestFocus() const
798 {
799 if (IsCurrentFocus()) {
800 return;
801 }
802 auto context = NG::PipelineContext::GetCurrentContext();
803 CHECK_NULL_VOID(context);
804 context->AddDirtyFocus(GetFrameNode());
805 }
806
RequestFocusWithDefaultFocusFirstly()807 void FocusHub::RequestFocusWithDefaultFocusFirstly()
808 {
809 TAG_LOGD(AceLogTag::ACE_FOCUS, "Request focus with default focus on node: %{public}s/%{public}d.",
810 GetFrameName().c_str(), GetFrameId());
811 auto pipeline = PipelineContext::GetCurrentContext();
812 CHECK_NULL_VOID(pipeline);
813
814 RefPtr<FocusHub> viewScope;
815 if (GetFrameName() == V2::MENU_WRAPPER_ETS_TAG) {
816 viewScope = GetChildren().front();
817 } else {
818 viewScope = Claim(this);
819 }
820 if (!viewScope) {
821 pipeline->AddDirtyDefaultFocus(GetFrameNode());
822 return;
823 }
824
825 auto screenNode = pipeline->GetScreenNode();
826 if (!screenNode || viewScope->GetFrameName() != V2::PAGE_ETS_TAG) {
827 auto viewRootScope = viewScope->GetMainViewRootScope();
828 if (viewRootScope && viewScope->GetIsViewRootScopeFocused()) {
829 viewRootScope->SetFocusDependence(FocusDependence::SELF);
830 }
831 }
832
833 pipeline->AddDirtyDefaultFocus(viewScope->GetFrameNode());
834 }
835
RequestNextFocus(FocusStep moveStep,const RectF & rect)836 bool FocusHub::RequestNextFocus(FocusStep moveStep, const RectF& rect)
837 {
838 TAG_LOGI(AceLogTag::ACE_FOCUS, "Request next focus on node: %{public}s/%{public}d by step: %{public}d.",
839 GetFrameName().c_str(), GetFrameId(), moveStep);
840 SetScopeFocusAlgorithm();
841 if (!focusAlgorithm_.getNextFocusNode) {
842 if (focusAlgorithm_.scopeType == ScopeType::PROJECT_AREA) {
843 auto lastFocusNode = lastWeakFocusNode_.Upgrade();
844 CHECK_NULL_RETURN(lastFocusNode, false);
845 RefPtr<FocusHub> nextFocusHub = nullptr;
846 if (IsFocusStepTab(moveStep)) {
847 nextFocusHub = lastFocusNode->GetNearestNodeByProjectArea(
848 GetChildren(), moveStep == FocusStep::TAB ? FocusStep::RIGHT : FocusStep::LEFT);
849 }
850 if (!nextFocusHub) {
851 nextFocusHub = lastFocusNode->GetNearestNodeByProjectArea(GetChildren(), moveStep);
852 }
853 if (!nextFocusHub || nextFocusHub == lastFocusNode) {
854 TAG_LOGI(
855 AceLogTag::ACE_FOCUS, "Request next focus failed becase cannot find next node by project area.");
856 return false;
857 }
858 auto ret = TryRequestFocus(nextFocusHub, rect, moveStep);
859 TAG_LOGI(AceLogTag::ACE_FOCUS,
860 "Request next focus by project area. Next focus node is %{public}s/%{public}d. Return %{public}d",
861 nextFocusHub->GetFrameName().c_str(), nextFocusHub->GetFrameId(), ret);
862 return ret;
863 }
864 if (!IsFocusStepTab(moveStep) && focusAlgorithm_.isVertical != IsFocusStepVertical(moveStep)) {
865 TAG_LOGI(AceLogTag::ACE_FOCUS,
866 "Request next focus failed because direction of node(%{public}d) is different with step(%{public}d).",
867 focusAlgorithm_.isVertical, moveStep);
868 return false;
869 }
870 auto ret = GoToNextFocusLinear(moveStep, rect);
871 TAG_LOGI(AceLogTag::ACE_FOCUS, "Request next focus by default linear algorithm. Return %{public}d.", ret);
872 return ret;
873 }
874 if (!lastWeakFocusNode_.Upgrade()) {
875 return false;
876 }
877 WeakPtr<FocusHub> nextFocusHubWeak;
878 focusAlgorithm_.getNextFocusNode(moveStep, lastWeakFocusNode_, nextFocusHubWeak);
879 auto nextFocusHub = nextFocusHubWeak.Upgrade();
880 if (!nextFocusHub || nextFocusHub == lastWeakFocusNode_.Upgrade()) {
881 TAG_LOGI(AceLogTag::ACE_FOCUS, "Request next focus failed by custom focus algorithm.");
882 return false;
883 }
884 auto ret = TryRequestFocus(nextFocusHub, rect, moveStep);
885 TAG_LOGI(AceLogTag::ACE_FOCUS,
886 "Request next focus by custom focus algorithm. Next focus node is %{public}s/%{public}d. Return %{public}d",
887 nextFocusHub->GetFrameName().c_str(), nextFocusHub->GetFrameId(), ret);
888 return ret;
889 }
890
FocusToHeadOrTailChild(bool isHead)891 bool FocusHub::FocusToHeadOrTailChild(bool isHead)
892 {
893 if (!IsFocusableWholePath()) {
894 return false;
895 }
896 if (focusType_ != FocusType::SCOPE || (focusType_ == FocusType::SCOPE && focusDepend_ == FocusDependence::SELF)) {
897 return RequestFocusImmediately();
898 }
899
900 std::list<RefPtr<FocusHub>> focusNodes;
901 FlushChildrenFocusHub(focusNodes);
902 bool canChildBeFocused = false;
903 if (isHead) {
904 canChildBeFocused = std::any_of(focusNodes.begin(), focusNodes.end(),
905 [](const RefPtr<FocusHub>& node) { return node->FocusToHeadOrTailChild(true); });
906 } else {
907 canChildBeFocused = std::any_of(focusNodes.rbegin(), focusNodes.rend(),
908 [](const RefPtr<FocusHub>& node) { return node->FocusToHeadOrTailChild(false); });
909 }
910
911 if (focusDepend_ == FocusDependence::CHILD) {
912 return canChildBeFocused;
913 }
914 if (focusDepend_ == FocusDependence::AUTO) {
915 if (!canChildBeFocused) {
916 return RequestFocusImmediately();
917 }
918 return canChildBeFocused;
919 }
920 return false;
921 }
922
OnClick(const KeyEvent & event)923 bool FocusHub::OnClick(const KeyEvent& event)
924 {
925 auto onClickCallback = GetOnClickCallback();
926 if (onClickCallback) {
927 auto info = GestureEvent();
928 info.SetTimeStamp(event.timeStamp);
929 auto geometryNode = GetGeometryNode();
930 CHECK_NULL_RETURN(geometryNode, false);
931 auto rect = geometryNode->GetFrameRect();
932 info.SetGlobalLocation(Offset((rect.Left() + rect.Right()) / 2, (rect.Top() + rect.Bottom()) / 2));
933 info.SetLocalLocation(Offset((rect.Right() - rect.Left()) / 2, (rect.Bottom() - rect.Top()) / 2));
934 info.SetSourceDevice(event.sourceType);
935 info.SetDeviceId(event.deviceId);
936 onClickCallback(info);
937 return true;
938 }
939 return false;
940 }
941
SwitchFocus(const RefPtr<FocusHub> & focusNode)942 void FocusHub::SwitchFocus(const RefPtr<FocusHub>& focusNode)
943 {
944 if (focusType_ != FocusType::SCOPE) {
945 TAG_LOGW(AceLogTag::ACE_FOCUS, "SwitchFocus: parent focus node is not a scope!");
946 return;
947 }
948 std::list<RefPtr<FocusHub>> focusNodes;
949 FlushChildrenFocusHub(focusNodes);
950
951 auto focusNodeNeedBlur = lastWeakFocusNode_.Upgrade();
952 lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(focusNode));
953
954 TAG_LOGD(AceLogTag::ACE_FOCUS, "Switch focus from %{public}s/%{public}d to %{public}s/%{public}d",
955 focusNodeNeedBlur ? focusNodeNeedBlur->GetFrameName().c_str() : "NULL",
956 focusNodeNeedBlur ? focusNodeNeedBlur->GetFrameId() : -1, focusNode->GetFrameName().c_str(),
957 focusNode->GetFrameId());
958 if (IsCurrentFocus()) {
959 if (focusNodeNeedBlur && focusNodeNeedBlur != focusNode) {
960 focusNodeNeedBlur->LostFocus();
961 }
962 } else {
963 RequestFocusImmediately();
964 }
965 }
966
GoToNextFocusLinear(FocusStep step,const RectF & rect)967 bool FocusHub::GoToNextFocusLinear(FocusStep step, const RectF& rect)
968 {
969 if (step == FocusStep::NONE) {
970 return false;
971 }
972 bool reverse = !IsFocusStepForward(step);
973 if (AceApplicationInfo::GetInstance().IsRightToLeft()) {
974 reverse = !reverse;
975 }
976 std::list<RefPtr<FocusHub>> focusNodes;
977 auto itNewFocusNode = FlushChildrenFocusHub(focusNodes);
978 if (focusNodes.empty()) {
979 return false;
980 }
981 if (itNewFocusNode == focusNodes.end()) {
982 itNewFocusNode = focusNodes.begin();
983 }
984 if (reverse) {
985 if (itNewFocusNode == focusNodes.begin()) {
986 itNewFocusNode = focusNodes.end();
987 return false;
988 }
989 --itNewFocusNode;
990
991 while (itNewFocusNode != focusNodes.begin()) {
992 if (TryRequestFocus(*itNewFocusNode, rect, step)) {
993 return true;
994 }
995 --itNewFocusNode;
996 }
997 if (itNewFocusNode == focusNodes.begin()) {
998 if (TryRequestFocus(*itNewFocusNode, rect, step)) {
999 return true;
1000 }
1001 }
1002 } else {
1003 if (itNewFocusNode != focusNodes.end()) {
1004 ++itNewFocusNode;
1005 }
1006 while (itNewFocusNode != focusNodes.end()) {
1007 if (TryRequestFocus(*itNewFocusNode, rect, step)) {
1008 return true;
1009 }
1010 ++itNewFocusNode;
1011 }
1012 }
1013
1014 return false;
1015 }
1016
TryRequestFocus(const RefPtr<FocusHub> & focusNode,const RectF & rect,FocusStep step)1017 bool FocusHub::TryRequestFocus(const RefPtr<FocusHub>& focusNode, const RectF& rect, FocusStep step)
1018 {
1019 if (IsFocusStepTab(step) && focusNode->AcceptFocusOfSpecifyChild(step)) {
1020 return focusNode->RequestFocusImmediately();
1021 }
1022 if (rect.IsValid()) {
1023 RectF childRect;
1024 if (!CalculateRect(focusNode, childRect) ||
1025 !focusNode->AcceptFocusByRectOfLastFocus(rect - childRect.GetOffset())) {
1026 return false;
1027 }
1028 }
1029 return focusNode->RequestFocusImmediately();
1030 }
1031
CalculatePosition()1032 bool FocusHub::CalculatePosition()
1033 {
1034 std::list<RefPtr<FocusHub>> focusNodes;
1035 FlushChildrenFocusHub(focusNodes);
1036 auto lastFocusNode = lastWeakFocusNode_.Upgrade();
1037 CHECK_NULL_RETURN(lastFocusNode, false);
1038
1039 RectF childRect;
1040 if (!CalculateRect(lastFocusNode, childRect)) {
1041 return false;
1042 }
1043
1044 if (lastFocusNode->IsChild()) {
1045 auto lastFocusGeometryNode = lastFocusNode->GetGeometryNode();
1046 CHECK_NULL_RETURN(lastFocusGeometryNode, false);
1047 RectF rect(childRect.GetOffset(), lastFocusGeometryNode->GetFrameSize());
1048 lastFocusNode->SetRect(rect);
1049 SetRect(rect);
1050 } else {
1051 SetRect(lastFocusNode->GetRect() + childRect.GetOffset());
1052 }
1053
1054 return true;
1055 }
1056
SetScopeFocusAlgorithm()1057 void FocusHub::SetScopeFocusAlgorithm()
1058 {
1059 auto frame = GetFrameNode();
1060 CHECK_NULL_VOID(frame);
1061 auto pattern = frame->GetPattern();
1062 CHECK_NULL_VOID(pattern);
1063 focusAlgorithm_ = pattern->GetScopeFocusAlgorithm();
1064 }
1065
SetLastFocusNodeIndex(const RefPtr<FocusHub> & focusNode)1066 void FocusHub::SetLastFocusNodeIndex(const RefPtr<FocusHub>& focusNode)
1067 {
1068 auto frame = GetFrameNode();
1069 CHECK_NULL_VOID(frame);
1070 auto pattern = frame->GetPattern();
1071 CHECK_NULL_VOID(pattern);
1072 lastFocusNodeIndex_ = pattern->GetFocusNodeIndex(focusNode);
1073 }
1074
ScrollToLastFocusIndex() const1075 void FocusHub::ScrollToLastFocusIndex() const
1076 {
1077 if (lastFocusNodeIndex_ == -1) {
1078 return;
1079 }
1080 auto frame = GetFrameNode();
1081 CHECK_NULL_VOID(frame);
1082 auto pattern = frame->GetPattern();
1083 CHECK_NULL_VOID(pattern);
1084 pattern->ScrollToFocusNodeIndex(lastFocusNodeIndex_);
1085 }
1086
OnFocus()1087 void FocusHub::OnFocus()
1088 {
1089 if (focusType_ == FocusType::NODE) {
1090 OnFocusNode();
1091 } else if (focusType_ == FocusType::SCOPE) {
1092 OnFocusScope();
1093 }
1094 auto frameNode = GetFrameNode();
1095 CHECK_NULL_VOID(frameNode);
1096 auto curPattern = frameNode->GetPattern<NG::Pattern>();
1097 CHECK_NULL_VOID(curPattern);
1098 bool isNeedKeyboard = curPattern->NeedSoftKeyboard();
1099 auto pipeline = PipelineContext::GetCurrentContext();
1100 CHECK_NULL_VOID(pipeline);
1101 pipeline->SetNeedSoftKeyboard(isNeedKeyboard);
1102 }
1103
OnBlur()1104 void FocusHub::OnBlur()
1105 {
1106 if (focusType_ == FocusType::NODE) {
1107 OnBlurNode();
1108 } else if (focusType_ == FocusType::SCOPE) {
1109 OnBlurScope();
1110 }
1111 auto pipeline = PipelineContext::GetCurrentContext();
1112 CHECK_NULL_VOID(pipeline);
1113 if (blurReason_ != BlurReason::WINDOW_BLUR) {
1114 pipeline->SetNeedSoftKeyboard(false);
1115 } else {
1116 pipeline->SetNeedSoftKeyboard(std::nullopt);
1117 }
1118 }
1119
IsCloseKeyboard(RefPtr<FrameNode> frameNode)1120 void FocusHub::IsCloseKeyboard(RefPtr<FrameNode> frameNode)
1121 {
1122 #if defined(ENABLE_STANDARD_INPUT)
1123 // If focus pattern does not need softkeyboard, close it, not in windowScene.
1124 auto curPattern = frameNode->GetPattern<NG::Pattern>();
1125 CHECK_NULL_VOID(curPattern);
1126 bool isNeedKeyBoard = curPattern->NeedSoftKeyboard();
1127 if (!isNeedKeyBoard) {
1128 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "FrameNode(%{public}s/%{public}d) notNeedSoftKeyboard.",
1129 frameNode->GetTag().c_str(), frameNode->GetId());
1130 auto inputMethod = MiscServices::InputMethodController::GetInstance();
1131 if (inputMethod) {
1132 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "SoftKeyboard Closes Successfully.");
1133 inputMethod->Close();
1134 }
1135 }
1136 #endif
1137 }
1138
NavCloseKeyboard()1139 void FocusHub::NavCloseKeyboard()
1140 {
1141 #if defined(ENABLE_STANDARD_INPUT)
1142 // If Nav, close it
1143 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Nav CloseKeyboard FrameNode notNeedSoftKeyboard.");
1144 auto inputMethod = MiscServices::InputMethodController::GetInstance();
1145 if (inputMethod) {
1146 inputMethod->RequestHideInput();
1147 inputMethod->Close();
1148 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "Nav CloseKeyboard SoftKeyboard Closes Successfully.");
1149 }
1150 #endif
1151 }
1152
PushPageCloseKeyboard()1153 void FocusHub::PushPageCloseKeyboard()
1154 {
1155 #if defined(ENABLE_STANDARD_INPUT)
1156 // If pushpage, close it
1157 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "PageChange CloseKeyboard FrameNode notNeedSoftKeyboard.");
1158 auto inputMethod = MiscServices::InputMethodController::GetInstance();
1159 if (inputMethod) {
1160 inputMethod->Close();
1161 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "PageChange CloseKeyboard SoftKeyboard Closes Successfully.");
1162 }
1163 #endif
1164 }
1165
OnFocusNode()1166 void FocusHub::OnFocusNode()
1167 {
1168 TAG_LOGI(AceLogTag::ACE_FOCUS, "Node(%{public}s/%{public}d) on focus", GetFrameName().c_str(), GetFrameId());
1169 if (onFocusInternal_) {
1170 onFocusInternal_();
1171 }
1172 auto pipeline = PipelineContext::GetCurrentContext();
1173 CHECK_NULL_VOID(pipeline);
1174 pipeline->AddAfterLayoutTask([weak = WeakClaim(this)]() {
1175 auto focusHub = weak.Upgrade();
1176 CHECK_NULL_VOID(focusHub);
1177 auto onFocusCallback = focusHub->GetOnFocusCallback();
1178 if (onFocusCallback) {
1179 onFocusCallback();
1180 }
1181 });
1182 auto parentFocusHub = GetParentFocusHub();
1183 if (parentFocusHub) {
1184 parentFocusHub->SetLastFocusNodeIndex(AceType::Claim(this));
1185 }
1186 HandleParentScroll(); // If current focus node has a scroll parent. Handle the scroll event.
1187 auto rootNode = pipeline->GetRootElement();
1188 auto rootFocusHub = rootNode ? rootNode->GetFocusHub() : nullptr;
1189 if (rootFocusHub && pipeline->GetIsFocusActive()) {
1190 rootFocusHub->ClearAllFocusState();
1191 rootFocusHub->PaintAllFocusState();
1192 }
1193 auto frameNode = GetFrameNode();
1194 CHECK_NULL_VOID(frameNode);
1195 frameNode->OnAccessibilityEvent(AccessibilityEventType::FOCUS);
1196
1197 if (frameNode->GetFocusType() == FocusType::NODE) {
1198 pipeline->SetFocusNode(frameNode);
1199 }
1200
1201 pipeline->RequestFrame();
1202 }
1203
OnBlurNode()1204 void FocusHub::OnBlurNode()
1205 {
1206 TAG_LOGI(AceLogTag::ACE_FOCUS, "Node(%{public}s/%{public}d) on blur by %{public}d", GetFrameName().c_str(),
1207 GetFrameId(), blurReason_);
1208 if (onBlurInternal_) {
1209 onBlurInternal_();
1210 }
1211 if (onBlurReasonInternal_) {
1212 onBlurReasonInternal_(blurReason_);
1213 }
1214 auto pipeline = PipelineContext::GetCurrentContext();
1215 CHECK_NULL_VOID(pipeline);
1216 pipeline->AddAfterLayoutTask([weak = WeakClaim(this)]() {
1217 auto focusHub = weak.Upgrade();
1218 CHECK_NULL_VOID(focusHub);
1219 auto onBlurCallback = focusHub->GetOnBlurCallback();
1220 if (onBlurCallback) {
1221 onBlurCallback();
1222 }
1223 });
1224 if (blurReason_ != BlurReason::FRAME_DESTROY) {
1225 ClearFocusState();
1226 }
1227 auto rootNode = pipeline->GetRootElement();
1228 auto rootFocusHub = rootNode ? rootNode->GetFocusHub() : nullptr;
1229 if (rootFocusHub && pipeline->GetIsFocusActive()) {
1230 rootFocusHub->ClearAllFocusState();
1231 rootFocusHub->PaintAllFocusState();
1232 }
1233 auto frameNode = GetFrameNode();
1234 CHECK_NULL_VOID(frameNode);
1235 if (frameNode->GetFocusType() == FocusType::NODE && frameNode == pipeline->GetFocusNode()) {
1236 pipeline->SetFocusNode(nullptr);
1237 }
1238
1239 pipeline->RequestFrame();
1240 }
1241
CheckFocusStateStyle(bool onFocus)1242 void FocusHub::CheckFocusStateStyle(bool onFocus)
1243 {
1244 auto eventHub = eventHub_.Upgrade();
1245 CHECK_NULL_VOID(eventHub);
1246 if (onFocus) {
1247 eventHub->UpdateCurrentUIState(UI_STATE_FOCUSED);
1248 } else {
1249 eventHub->ResetCurrentUIState(UI_STATE_FOCUSED);
1250 }
1251 }
1252
HasFocusStateStyle()1253 bool FocusHub::HasFocusStateStyle()
1254 {
1255 auto eventHub = eventHub_.Upgrade();
1256 CHECK_NULL_RETURN(eventHub, false);
1257 return eventHub->HasStateStyle(UI_STATE_FOCUSED);
1258 }
1259
OnFocusScope(bool currentHasFocused)1260 void FocusHub::OnFocusScope(bool currentHasFocused)
1261 {
1262 if (focusDepend_ == FocusDependence::SELF) {
1263 lastWeakFocusNode_ = nullptr;
1264 OnFocusNode();
1265 return;
1266 }
1267
1268 std::list<RefPtr<FocusHub>> focusNodes;
1269 auto itLastFocusNode = FlushChildrenFocusHub(focusNodes);
1270 bool isAnyChildFocusable = focusNodes.empty()
1271 ? false
1272 : std::any_of(focusNodes.begin(), focusNodes.end(),
1273 [](const RefPtr<FocusHub>& focusNode) { return focusNode->IsFocusable(); });
1274
1275 if (focusDepend_ == FocusDependence::AUTO && !isAnyChildFocusable) {
1276 lastWeakFocusNode_ = nullptr;
1277 OnFocusNode();
1278 return;
1279 }
1280
1281 if ((focusDepend_ == FocusDependence::AUTO || focusDepend_ == FocusDependence::CHILD) && isAnyChildFocusable) {
1282 auto itFocusNode = itLastFocusNode;
1283 do {
1284 if (itLastFocusNode == focusNodes.end()) {
1285 itLastFocusNode = focusNodes.begin();
1286 lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*itLastFocusNode));
1287 if (itLastFocusNode == itFocusNode) {
1288 break;
1289 }
1290 }
1291 lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*itLastFocusNode));
1292 if ((*itLastFocusNode)->RequestFocusImmediately()) {
1293 if (!currentHasFocused) {
1294 OnFocusNode();
1295 }
1296 return;
1297 }
1298 } while ((++itLastFocusNode) != itFocusNode);
1299
1300 // Not found any focusable node, clear focus.
1301 itLastFocusNode = focusNodes.end();
1302 lastWeakFocusNode_ = nullptr;
1303 }
1304 }
1305
OnBlurScope()1306 void FocusHub::OnBlurScope()
1307 {
1308 std::list<RefPtr<FocusHub>> focusNodes;
1309 FlushChildrenFocusHub(focusNodes);
1310 OnBlurNode();
1311 auto lastFocusNode = lastWeakFocusNode_.Upgrade();
1312 if (lastFocusNode) {
1313 lastFocusNode->LostFocus(blurReason_);
1314 }
1315 }
1316
PaintFocusState(bool isNeedStateStyles,bool forceUpdate)1317 bool FocusHub::PaintFocusState(bool isNeedStateStyles, bool forceUpdate)
1318 {
1319 auto context = PipelineContext::GetCurrentContext();
1320 CHECK_NULL_RETURN(context, false);
1321 auto frameNode = GetFrameNode();
1322 CHECK_NULL_RETURN(frameNode, false);
1323 auto renderContext = frameNode->GetRenderContext();
1324 CHECK_NULL_RETURN(renderContext, false);
1325 if (!forceUpdate && (!context->GetIsFocusActive() || !IsNeedPaintFocusState())) {
1326 return false;
1327 }
1328
1329 if (HasFocusStateStyle()) {
1330 if (isNeedStateStyles) {
1331 // do focus state style.
1332 CheckFocusStateStyle(true);
1333 }
1334 return true;
1335 }
1336
1337 if (focusStyleType_ == FocusStyleType::NONE) {
1338 return false;
1339 }
1340
1341 if (focusStyleType_ == FocusStyleType::CUSTOM_REGION) {
1342 CHECK_NULL_RETURN(getInnerFocusRectFunc_, false);
1343 RoundRect focusRectInner;
1344 focusRectInner.SetRect({ -1, -1, -1, -1 });
1345 getInnerFocusRectFunc_(focusRectInner);
1346 if (!focusRectInner.GetRect().IsValid()) {
1347 return false;
1348 }
1349 return PaintInnerFocusState(focusRectInner, forceUpdate);
1350 }
1351
1352 auto appTheme = context->GetTheme<AppTheme>();
1353 CHECK_NULL_RETURN(appTheme, false);
1354 Color paintColor;
1355 if (HasPaintColor()) {
1356 paintColor = GetPaintColor();
1357 } else {
1358 paintColor = appTheme->GetFocusColor();
1359 }
1360 Dimension paintWidth;
1361 if (HasPaintWidth()) {
1362 paintWidth = GetPaintWidth();
1363 } else {
1364 paintWidth = appTheme->GetFocusWidthVp();
1365 }
1366
1367 if (focusStyleType_ == FocusStyleType::CUSTOM_BORDER) {
1368 if (!HasPaintRect()) {
1369 return false;
1370 }
1371 renderContext->PaintFocusState(GetPaintRect(), paintColor, paintWidth);
1372 return true;
1373 }
1374
1375 Dimension focusPaddingVp = Dimension(0.0, DimensionUnit::VP);
1376 if (HasFocusPadding()) {
1377 focusPaddingVp = GetFocusPadding();
1378 } else {
1379 if (focusStyleType_ == FocusStyleType::INNER_BORDER) {
1380 focusPaddingVp = -appTheme->GetFocusWidthVp();
1381 } else if (focusStyleType_ == FocusStyleType::OUTER_BORDER) {
1382 focusPaddingVp = appTheme->GetFocusOutPaddingVp();
1383 }
1384 }
1385 if (HasPaintRect()) {
1386 renderContext->PaintFocusState(GetPaintRect(), focusPaddingVp, paintColor, paintWidth);
1387 } else {
1388 renderContext->PaintFocusState(focusPaddingVp, paintColor, paintWidth);
1389 }
1390 return true;
1391 }
1392
PaintAllFocusState()1393 bool FocusHub::PaintAllFocusState()
1394 {
1395 if (PaintFocusState()) {
1396 return !isFocusActiveWhenFocused_;
1397 }
1398 std::list<RefPtr<FocusHub>> focusNodes;
1399 FlushChildrenFocusHub(focusNodes);
1400 auto lastFocusNode = lastWeakFocusNode_.Upgrade();
1401 if (lastFocusNode && lastFocusNode->IsCurrentFocus() && lastFocusNode->IsFocusableNode()) {
1402 return lastFocusNode->PaintAllFocusState();
1403 }
1404 if (onPaintFocusStateCallback_) {
1405 return onPaintFocusStateCallback_();
1406 }
1407 return false;
1408 }
1409
PaintInnerFocusState(const RoundRect & paintRect,bool forceUpdate)1410 bool FocusHub::PaintInnerFocusState(const RoundRect& paintRect, bool forceUpdate)
1411 {
1412 auto context = PipelineContext::GetCurrentContext();
1413 CHECK_NULL_RETURN(context, false);
1414 auto frameNode = GetFrameNode();
1415 CHECK_NULL_RETURN(frameNode, false);
1416 auto renderContext = frameNode->GetRenderContext();
1417 CHECK_NULL_RETURN(renderContext, false);
1418 if (!forceUpdate && (!context->GetIsFocusActive() || !IsNeedPaintFocusState())) {
1419 return false;
1420 }
1421 auto appTheme = context->GetTheme<AppTheme>();
1422 CHECK_NULL_RETURN(appTheme, false);
1423 Color paintColor;
1424 if (HasPaintColor()) {
1425 paintColor = GetPaintColor();
1426 } else {
1427 paintColor = appTheme->GetFocusColor();
1428 }
1429 Dimension paintWidth;
1430 if (HasPaintWidth()) {
1431 paintWidth = GetPaintWidth();
1432 } else {
1433 paintWidth = appTheme->GetFocusWidthVp();
1434 }
1435 renderContext->ClearFocusState();
1436 renderContext->PaintFocusState(paintRect, paintColor, paintWidth);
1437 return true;
1438 }
1439
ClearFocusState(bool isNeedStateStyles)1440 void FocusHub::ClearFocusState(bool isNeedStateStyles)
1441 {
1442 if (isNeedStateStyles) {
1443 // check focus state style.
1444 CheckFocusStateStyle(false);
1445 }
1446 if (onClearFocusStateCallback_) {
1447 onClearFocusStateCallback_();
1448 }
1449 if (focusStyleType_ != FocusStyleType::NONE) {
1450 auto frameNode = GetFrameNode();
1451 CHECK_NULL_VOID(frameNode);
1452 auto renderContext = frameNode->GetRenderContext();
1453 CHECK_NULL_VOID(renderContext);
1454 renderContext->ClearFocusState();
1455 }
1456 }
1457
ClearAllFocusState()1458 void FocusHub::ClearAllFocusState()
1459 {
1460 ClearFocusState();
1461 std::list<RefPtr<FocusHub>> focusNodes;
1462 FlushChildrenFocusHub(focusNodes);
1463 auto lastFocusNode = lastWeakFocusNode_.Upgrade();
1464 if (lastFocusNode) {
1465 lastFocusNode->ClearAllFocusState();
1466 }
1467 }
1468
IsNeedPaintFocusState()1469 bool FocusHub::IsNeedPaintFocusState()
1470 {
1471 if (currentFocus_ && IsFocusableNode() &&
1472 (focusDepend_ == FocusDependence::SELF || focusType_ == FocusType::NODE)) {
1473 return focusStyleType_ != FocusStyleType::NONE || HasFocusStateStyle();
1474 }
1475 std::list<RefPtr<FocusHub>> focusNodes;
1476 FlushChildrenFocusHub(focusNodes);
1477 auto lastFocusNode = GetLastWeakFocusNode().Upgrade();
1478 while (lastFocusNode) {
1479 if (!lastFocusNode->IsCurrentFocus() || !lastFocusNode->IsFocusableNode()) {
1480 break;
1481 }
1482 if (lastFocusNode->GetFocusStyleType() != FocusStyleType::NONE || lastFocusNode->HasFocusStateStyle()) {
1483 return false;
1484 }
1485 focusNodes.clear();
1486 lastFocusNode->FlushChildrenFocusHub(focusNodes);
1487 lastFocusNode = lastFocusNode->GetLastWeakFocusNode().Upgrade();
1488 }
1489 return focusStyleType_ != FocusStyleType::NONE || HasFocusStateStyle();
1490 }
1491
AcceptFocusOfSpecifyChild(FocusStep step)1492 bool FocusHub::AcceptFocusOfSpecifyChild(FocusStep step)
1493 {
1494 if (focusType_ == FocusType::NODE) {
1495 return IsFocusable();
1496 }
1497 if (focusType_ != FocusType::SCOPE || !IsFocusableScope()) {
1498 return false;
1499 }
1500 if (focusDepend_ == FocusDependence::SELF) {
1501 return true;
1502 }
1503 std::list<RefPtr<FocusHub>> focusNodes;
1504 FlushChildrenFocusHub(focusNodes);
1505 bool canChildBeFocused = false;
1506 if (!focusNodes.empty()) {
1507 if (step == FocusStep::TAB) {
1508 auto iterNewFocusNode = focusNodes.begin();
1509 while (iterNewFocusNode != focusNodes.end()) {
1510 if (*iterNewFocusNode && (*iterNewFocusNode)->AcceptFocusOfSpecifyChild(step)) {
1511 lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*iterNewFocusNode));
1512 canChildBeFocused = true;
1513 break;
1514 }
1515 ++iterNewFocusNode;
1516 }
1517 } else if (step == FocusStep::SHIFT_TAB) {
1518 auto iterNewFocusNode = focusNodes.rbegin();
1519 while (iterNewFocusNode != focusNodes.rend()) {
1520 if (*iterNewFocusNode && (*iterNewFocusNode)->AcceptFocusOfSpecifyChild(step)) {
1521 lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*iterNewFocusNode));
1522 canChildBeFocused = true;
1523 break;
1524 }
1525 ++iterNewFocusNode;
1526 }
1527 }
1528 }
1529 if (focusDepend_ == FocusDependence::CHILD) {
1530 return canChildBeFocused;
1531 }
1532 return focusDepend_ == FocusDependence::AUTO;
1533 }
1534
AcceptFocusOfLastFocus()1535 bool FocusHub::AcceptFocusOfLastFocus()
1536 {
1537 if (focusType_ == FocusType::SCOPE) {
1538 auto lastFocusNode = lastWeakFocusNode_.Upgrade();
1539 return lastFocusNode ? lastFocusNode->AcceptFocusOfLastFocus() : false;
1540 }
1541 if (focusType_ == FocusType::NODE) {
1542 return IsFocusableWholePath();
1543 }
1544 return false;
1545 }
1546
AcceptFocusByRectOfLastFocus(const RectF & rect)1547 bool FocusHub::AcceptFocusByRectOfLastFocus(const RectF& rect)
1548 {
1549 if (focusType_ == FocusType::NODE) {
1550 return AcceptFocusByRectOfLastFocusNode(rect);
1551 }
1552 if (focusType_ == FocusType::SCOPE) {
1553 return AcceptFocusByRectOfLastFocusFlex(rect);
1554 }
1555 return false;
1556 }
1557
AcceptFocusByRectOfLastFocusNode(const RectF & rect)1558 bool FocusHub::AcceptFocusByRectOfLastFocusNode(const RectF& rect)
1559 {
1560 return IsFocusableWholePath();
1561 }
1562
AcceptFocusByRectOfLastFocusScope(const RectF & rect)1563 bool FocusHub::AcceptFocusByRectOfLastFocusScope(const RectF& rect)
1564 {
1565 std::list<RefPtr<FocusHub>> focusNodes;
1566 auto itLastFocusNode = FlushChildrenFocusHub(focusNodes);
1567 if (focusNodes.empty()) {
1568 return false;
1569 }
1570 auto itFocusNode = itLastFocusNode;
1571 do {
1572 if (itLastFocusNode == focusNodes.end()) {
1573 itLastFocusNode = focusNodes.begin();
1574 lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*itLastFocusNode));
1575 if (itLastFocusNode == itFocusNode) {
1576 break;
1577 }
1578 }
1579 RectF childRect;
1580 if (!CalculateRect(*itLastFocusNode, childRect)) {
1581 continue;
1582 }
1583
1584 if ((*itLastFocusNode)->AcceptFocusByRectOfLastFocus(rect - childRect.GetOffset())) {
1585 lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*itLastFocusNode));
1586 return true;
1587 }
1588 } while ((++itLastFocusNode) != itFocusNode);
1589 if (itLastFocusNode == focusNodes.end()) {
1590 lastWeakFocusNode_ = nullptr;
1591 } else {
1592 lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*itLastFocusNode));
1593 }
1594
1595 return false;
1596 }
1597
AcceptFocusByRectOfLastFocusFlex(const RectF & rect)1598 bool FocusHub::AcceptFocusByRectOfLastFocusFlex(const RectF& rect)
1599 {
1600 if (!rect.IsValid()) {
1601 return false;
1602 }
1603
1604 if (focusType_ != FocusType::SCOPE || !IsFocusableWholePath()) {
1605 return false;
1606 }
1607 if (focusDepend_ == FocusDependence::SELF) {
1608 return true;
1609 }
1610 std::list<RefPtr<FocusHub>> focusNodes;
1611 FlushChildrenFocusHub(focusNodes);
1612 bool canChildBeFocused = false;
1613 OffsetF offset;
1614 auto itNewFocusNode = focusNodes.end();
1615 double minVal = std::numeric_limits<double>::max();
1616 for (auto it = focusNodes.begin(); it != focusNodes.end(); ++it) {
1617 if (!(*it)->IsFocusable()) {
1618 continue;
1619 }
1620
1621 RectF childRect;
1622 if (!CalculateRect(*it, childRect)) {
1623 continue;
1624 }
1625
1626 if (!childRect.IsValid() || NearZero(childRect.Width()) || NearZero(childRect.Height())) {
1627 continue;
1628 }
1629
1630 OffsetF vec = childRect.Center() - rect.Center();
1631 double val = (vec.GetX() * vec.GetX()) + (vec.GetY() * vec.GetY());
1632 if (minVal > val) {
1633 minVal = val;
1634 itNewFocusNode = it;
1635 offset = childRect.GetOffset();
1636 }
1637 }
1638
1639 if (itNewFocusNode != focusNodes.end() && (*itNewFocusNode)->AcceptFocusByRectOfLastFocus(rect - offset)) {
1640 lastWeakFocusNode_ = AceType::WeakClaim(AceType::RawPtr(*itNewFocusNode));
1641 canChildBeFocused = true;
1642 }
1643 if (focusDepend_ == FocusDependence::CHILD) {
1644 return canChildBeFocused;
1645 }
1646 return focusDepend_ == FocusDependence::AUTO;
1647 }
1648
CalculateRect(const RefPtr<FocusHub> & childNode,RectF & rect) const1649 bool FocusHub::CalculateRect(const RefPtr<FocusHub>& childNode, RectF& rect) const
1650 {
1651 auto childGeometryNode = childNode->GetGeometryNode();
1652 CHECK_NULL_RETURN(childGeometryNode, false);
1653 rect = childGeometryNode->GetFrameRect();
1654 return true;
1655 }
1656
IsFocusableByTab()1657 bool FocusHub::IsFocusableByTab()
1658 {
1659 if (focusType_ == FocusType::NODE) {
1660 return IsFocusableNodeByTab();
1661 }
1662 if (focusType_ == FocusType::SCOPE) {
1663 return IsFocusableScopeByTab();
1664 }
1665 return false;
1666 }
1667
IsFocusableNodeByTab()1668 bool FocusHub::IsFocusableNodeByTab()
1669 {
1670 auto parent = GetParentFocusHub();
1671 CHECK_NULL_RETURN(parent, GetTabIndex() == 0);
1672 return (GetTabIndex() == 0) && (parent->GetTabIndex() == 0);
1673 }
1674
IsFocusableScopeByTab()1675 bool FocusHub::IsFocusableScopeByTab()
1676 {
1677 std::list<RefPtr<FocusHub>> focusNodes;
1678 FlushChildrenFocusHub(focusNodes);
1679 if (!IsFocusableNodeByTab()) {
1680 return false;
1681 }
1682 if (focusNodes.empty()) {
1683 return true;
1684 }
1685 return std::any_of(focusNodes.begin(), focusNodes.end(),
1686 [](const RefPtr<FocusHub>& focusNode) { return focusNode->IsFocusableByTab(); });
1687 }
1688
IsFocusableWholePath()1689 bool FocusHub::IsFocusableWholePath()
1690 {
1691 auto parent = GetParentFocusHub();
1692 while (parent) {
1693 if (!parent->IsFocusableNode()) {
1694 return false;
1695 }
1696 parent = parent->GetParentFocusHub();
1697 }
1698 return IsFocusable();
1699 }
1700
IsOnRootTree() const1701 bool FocusHub::IsOnRootTree() const
1702 {
1703 auto parent = GetParentFocusHub();
1704 while (parent) {
1705 auto parentName = parent->GetFrameName();
1706 if (parentName == V2::ROOT_ETS_TAG) {
1707 return true;
1708 }
1709 parent = parent->GetParentFocusHub();
1710 }
1711 return false;
1712 }
1713
CollectTabIndexNodes(TabIndexNodeList & tabIndexNodes)1714 void FocusHub::CollectTabIndexNodes(TabIndexNodeList& tabIndexNodes)
1715 {
1716 if (GetTabIndex() > 0 && IsFocusableWholePath()) {
1717 tabIndexNodes.emplace_back(GetTabIndex(), WeakClaim(this));
1718 }
1719 if (GetFocusType() == FocusType::SCOPE) {
1720 std::list<RefPtr<FocusHub>> focusNodes;
1721 FlushChildrenFocusHub(focusNodes);
1722 for (auto& child : focusNodes) {
1723 child->CollectTabIndexNodes(tabIndexNodes);
1724 }
1725 }
1726 }
1727
GoToFocusByTabNodeIdx(TabIndexNodeList & tabIndexNodes,int32_t tabNodeIdx)1728 bool FocusHub::GoToFocusByTabNodeIdx(TabIndexNodeList& tabIndexNodes, int32_t tabNodeIdx)
1729 {
1730 auto iter = tabIndexNodes.begin();
1731 std::advance(iter, tabNodeIdx);
1732 if (iter == tabIndexNodes.end()) {
1733 return false;
1734 }
1735 auto nodeNeedToFocus = (*iter).second.Upgrade();
1736 if (!nodeNeedToFocus) {
1737 TAG_LOGW(AceLogTag::ACE_FOCUS, "Tab index node is null");
1738 return false;
1739 }
1740 auto nodeIdNeedToFocus = nodeNeedToFocus->GetFrameId();
1741 TAG_LOGI(AceLogTag::ACE_FOCUS, "Move focus to tab index node(%{public}d: %{public}s/%{public}d)", tabNodeIdx,
1742 nodeNeedToFocus->GetFrameName().c_str(), nodeNeedToFocus->GetFrameId());
1743 if (nodeNeedToFocus->GetFocusType() == FocusType::SCOPE && !nodeNeedToFocus->IsDefaultGroupHasFocused()) {
1744 auto defaultFocusNode = nodeNeedToFocus->GetChildFocusNodeByType(FocusNodeType::GROUP_DEFAULT);
1745 if (defaultFocusNode) {
1746 if (!defaultFocusNode->IsFocusableWholePath()) {
1747 TAG_LOGI(AceLogTag::ACE_FOCUS, "node(%{public}d) is not focusable", tabNodeIdx);
1748 return false;
1749 }
1750 nodeNeedToFocus->SetIsDefaultGroupHasFocused(true);
1751 if (defaultFocusNode->RequestFocusImmediately()) {
1752 lastTabIndexNodeId_ = nodeIdNeedToFocus;
1753 return true;
1754 }
1755 return false;
1756 }
1757 }
1758 if (!nodeNeedToFocus->IsFocusableWholePath()) {
1759 TAG_LOGI(AceLogTag::ACE_FOCUS, "node(%{public}d) is not focusable", tabNodeIdx);
1760 return false;
1761 }
1762 if (nodeNeedToFocus->RequestFocusImmediately()) {
1763 lastTabIndexNodeId_ = nodeIdNeedToFocus;
1764 return true;
1765 }
1766 return false;
1767 }
1768
GetChildFocusNodeByType(FocusNodeType nodeType)1769 RefPtr<FocusHub> FocusHub::GetChildFocusNodeByType(FocusNodeType nodeType)
1770 {
1771 if (nodeType == FocusNodeType::DEFAULT && IsDefaultFocus() && IsFocusable()) {
1772 return AceType::Claim(this);
1773 }
1774 if (nodeType == FocusNodeType::GROUP_DEFAULT && IsDefaultGroupFocus() && IsFocusable()) {
1775 return AceType::Claim(this);
1776 }
1777 if (focusType_ != FocusType::SCOPE) {
1778 return nullptr;
1779 }
1780 std::list<RefPtr<FocusHub>> focusNodes;
1781 FlushChildrenFocusHub(focusNodes);
1782 for (const auto& child : focusNodes) {
1783 auto findNode = child->GetChildFocusNodeByType(nodeType);
1784 if (findNode) {
1785 return findNode;
1786 }
1787 }
1788 return nullptr;
1789 }
1790
GetChildFocusNodeById(const std::string & id)1791 RefPtr<FocusHub> FocusHub::GetChildFocusNodeById(const std::string& id)
1792 {
1793 if (id.empty()) {
1794 return nullptr;
1795 }
1796 if (GetInspectorKey().has_value() && GetInspectorKey().value() == id) {
1797 return AceType::Claim(this);
1798 }
1799 if (focusType_ == FocusType::SCOPE) {
1800 std::list<RefPtr<FocusHub>> focusNodes;
1801 FlushChildrenFocusHub(focusNodes);
1802 for (const auto& child : focusNodes) {
1803 auto findNode = child->GetChildFocusNodeById(id);
1804 if (findNode) {
1805 return findNode;
1806 }
1807 }
1808 }
1809 return nullptr;
1810 }
1811
HandleParentScroll() const1812 void FocusHub::HandleParentScroll() const
1813 {
1814 auto context = PipelineContext::GetCurrentContext();
1815 CHECK_NULL_VOID(context);
1816 if (!context->GetIsFocusActive() || (focusType_ != FocusType::NODE && !isFocusUnit_)) {
1817 return;
1818 }
1819 auto parent = GetParentFocusHub();
1820 RefPtr<FrameNode> parentFrame;
1821 RefPtr<Pattern> parentPattern;
1822 while (parent) {
1823 if (parent->isFocusUnit_) {
1824 return;
1825 }
1826 parentFrame = parent->GetFrameNode();
1827 if (!parentFrame) {
1828 parent = parent->GetParentFocusHub();
1829 continue;
1830 }
1831 parentPattern = parentFrame->GetPattern();
1832 if (parentPattern && parentPattern->ScrollToNode(GetFrameNode())) {
1833 return;
1834 }
1835 parent = parent->GetParentFocusHub();
1836 }
1837 }
1838
RequestFocusImmediatelyById(const std::string & id)1839 bool FocusHub::RequestFocusImmediatelyById(const std::string& id)
1840 {
1841 auto focusNode = GetChildFocusNodeById(id);
1842 if (!focusNode) {
1843 TAG_LOGI(AceLogTag::ACE_FOCUS, "Request focus id: %{public}s can not found.", id.c_str());
1844 return false;
1845 }
1846 auto result = true;
1847 if (!focusNode->IsFocusable()) {
1848 result = false;
1849 }
1850 TAG_LOGI(AceLogTag::ACE_FOCUS, "Request focus immediately by id: %{public}s. The node is %{public}s/%{public}d.",
1851 id.c_str(), focusNode->GetFrameName().c_str(), focusNode->GetFrameId());
1852 auto pipeline = PipelineContext::GetCurrentContext();
1853 CHECK_NULL_RETURN(pipeline, false);
1854 pipeline->AddDirtyRequestFocus(focusNode->GetFrameNode());
1855 return result;
1856 }
1857
GetFocusingTabNodeIdx(TabIndexNodeList & tabIndexNodes) const1858 int32_t FocusHub::GetFocusingTabNodeIdx(TabIndexNodeList& tabIndexNodes) const
1859 {
1860 if (lastTabIndexNodeId_ == DEFAULT_TAB_FOCUSED_INDEX) {
1861 return DEFAULT_TAB_FOCUSED_INDEX;
1862 }
1863 int32_t i = 0;
1864 for (auto& wpNode : tabIndexNodes) {
1865 auto node = wpNode.second.Upgrade();
1866 if (node && node->IsCurrentFocus() && node->GetFrameId() == lastTabIndexNodeId_) {
1867 return i;
1868 }
1869 ++i;
1870 }
1871 return DEFAULT_TAB_FOCUSED_INDEX;
1872 }
1873
HandleFocusByTabIndex(const KeyEvent & event)1874 bool FocusHub::HandleFocusByTabIndex(const KeyEvent& event)
1875 {
1876 if (event.code != KeyCode::KEY_TAB || event.action != KeyAction::DOWN) {
1877 return false;
1878 }
1879 auto pipeline = PipelineContext::GetCurrentContext();
1880 if (pipeline && pipeline->IsTabJustTriggerOnKeyEvent()) {
1881 return false;
1882 }
1883 TabIndexNodeList tabIndexNodes;
1884 tabIndexNodes.clear();
1885 CollectTabIndexNodes(tabIndexNodes);
1886 if (tabIndexNodes.empty()) {
1887 return false;
1888 }
1889 tabIndexNodes.sort([](std::pair<int32_t, WeakPtr<FocusHub>>& a, std::pair<int32_t, WeakPtr<FocusHub>>& b) {
1890 return a.first < b.first;
1891 });
1892 int32_t curTabFocusIndex = GetFocusingTabNodeIdx(tabIndexNodes);
1893 if ((curTabFocusIndex < 0 || curTabFocusIndex >= static_cast<int32_t>(tabIndexNodes.size())) &&
1894 curTabFocusIndex != DEFAULT_TAB_FOCUSED_INDEX) {
1895 TAG_LOGI(AceLogTag::ACE_FOCUS, "Current focused tabIndex: %{public}d is not valid. Use default focus system.",
1896 curTabFocusIndex);
1897 return false;
1898 }
1899 if (curTabFocusIndex == DEFAULT_TAB_FOCUSED_INDEX) {
1900 curTabFocusIndex = 0;
1901 } else {
1902 if (event.IsShiftWith(KeyCode::KEY_TAB)) {
1903 --curTabFocusIndex;
1904 } else {
1905 ++curTabFocusIndex;
1906 }
1907 if (curTabFocusIndex < 0 || curTabFocusIndex >= static_cast<int32_t>(tabIndexNodes.size())) {
1908 curTabFocusIndex = (curTabFocusIndex + static_cast<int32_t>(tabIndexNodes.size())) %
1909 static_cast<int32_t>(tabIndexNodes.size());
1910 }
1911 }
1912 return GoToFocusByTabNodeIdx(tabIndexNodes, curTabFocusIndex);
1913 }
1914
HasBackwardFocusMovementInChildren()1915 bool FocusHub::HasBackwardFocusMovementInChildren()
1916 {
1917 std::list<RefPtr<FocusHub>> children;
1918 FlushChildrenFocusHub(children);
1919 for (const auto& child : children) {
1920 if (child->HasBackwardFocusMovement()) {
1921 return true;
1922 }
1923 }
1924 return false;
1925 }
1926
HasForwardFocusMovementInChildren()1927 bool FocusHub::HasForwardFocusMovementInChildren()
1928 {
1929 std::list<RefPtr<FocusHub>> children;
1930 FlushChildrenFocusHub(children);
1931 for (const auto& child : children) {
1932 if (child->HasForwardFocusMovement()) {
1933 return true;
1934 }
1935 }
1936 return false;
1937 }
1938
ClearFocusMovementFlagsInChildren()1939 void FocusHub::ClearFocusMovementFlagsInChildren()
1940 {
1941 std::list<RefPtr<FocusHub>> children;
1942 FlushChildrenFocusHub(children);
1943 for (auto child : children) {
1944 child->ClearFocusMovementFlags();
1945 child->ClearFocusMovementFlagsInChildren();
1946 }
1947 }
1948
GetProjectAreaOnRect(const RectF & rect,const RectF & projectRect,FocusStep step)1949 double FocusHub::GetProjectAreaOnRect(const RectF& rect, const RectF& projectRect, FocusStep step)
1950 {
1951 float areaWidth = 0.0;
1952 float areaHeight = 0.0;
1953 switch (step) {
1954 case FocusStep::UP:
1955 if (rect.Top() < projectRect.Bottom() && rect.Right() > projectRect.Left() &&
1956 rect.Left() < projectRect.Right()) {
1957 areaWidth = std::min(rect.Right(), projectRect.Right()) - std::max(rect.Left(), projectRect.Left());
1958 areaHeight = std::min(rect.Bottom(), projectRect.Bottom()) - rect.Top();
1959 }
1960 break;
1961 case FocusStep::DOWN:
1962 if (rect.Bottom() > projectRect.Top() && rect.Right() > projectRect.Left() &&
1963 rect.Left() < projectRect.Right()) {
1964 areaWidth = std::min(rect.Right(), projectRect.Right()) - std::max(rect.Left(), projectRect.Left());
1965 areaHeight = rect.Bottom() - std::max(rect.Top(), projectRect.Top());
1966 }
1967 break;
1968 case FocusStep::LEFT:
1969 if (rect.Left() < projectRect.Right() && rect.Bottom() > projectRect.Top() &&
1970 rect.Top() < projectRect.Bottom()) {
1971 areaWidth = std::min(rect.Right(), projectRect.Right()) - rect.Left();
1972 areaHeight = std::min(rect.Bottom(), projectRect.Bottom()) - std::max(rect.Top(), projectRect.Top());
1973 }
1974 break;
1975 case FocusStep::RIGHT:
1976 if (rect.Right() > projectRect.Left() && rect.Bottom() > projectRect.Top() &&
1977 rect.Top() < projectRect.Bottom()) {
1978 areaWidth = rect.Right() - std::max(rect.Left(), projectRect.Left());
1979 areaHeight = std::min(rect.Bottom(), projectRect.Bottom()) - std::max(rect.Top(), projectRect.Top());
1980 }
1981 break;
1982 default:
1983 break;
1984 }
1985 return areaWidth * areaHeight;
1986 }
1987
GetNearestNodeByProjectArea(const std::list<RefPtr<FocusHub>> & allNodes,FocusStep step)1988 RefPtr<FocusHub> FocusHub::GetNearestNodeByProjectArea(const std::list<RefPtr<FocusHub>>& allNodes, FocusStep step)
1989 {
1990 CHECK_NULL_RETURN(!allNodes.empty(), nullptr);
1991 auto curFrameNode = GetFrameNode();
1992 CHECK_NULL_RETURN(curFrameNode, nullptr);
1993 auto curFrameOffset = curFrameNode->GetOffsetRelativeToWindow();
1994 auto curGeometryNode = curFrameNode->GetGeometryNode();
1995 CHECK_NULL_RETURN(curGeometryNode, nullptr);
1996 RectF curFrameRect = RectF(curFrameOffset, curGeometryNode->GetFrameRect().GetSize());
1997 curFrameRect.SetOffset(curFrameOffset);
1998 TAG_LOGD(AceLogTag::ACE_FOCUS,
1999 "Current focus node is %{public}s/%{public}d. Rect is {%{public}f,%{public}f,%{public}f,%{public}f}.",
2000 GetFrameName().c_str(), GetFrameId(), curFrameRect.Left(), curFrameRect.Top(), curFrameRect.Right(),
2001 curFrameRect.Bottom());
2002 bool isTabStep = IsFocusStepTab(step);
2003 double resDistance = !isTabStep ? std::numeric_limits<double>::max() : 0.0f;
2004 RefPtr<FocusHub> nextNode;
2005 for (const auto& node : allNodes) {
2006 if (!node || AceType::RawPtr(node) == this) {
2007 continue;
2008 }
2009 auto frameNode = node->GetFrameNode();
2010 if (!frameNode) {
2011 continue;
2012 }
2013 auto frameOffset = frameNode->GetOffsetRelativeToWindow();
2014 auto geometryNode = frameNode->GetGeometryNode();
2015 if (!geometryNode) {
2016 continue;
2017 }
2018 RectF frameRect = RectF(frameOffset, geometryNode->GetFrameRect().GetSize());
2019 auto realStep = step;
2020 if (step == FocusStep::TAB) {
2021 frameRect -= OffsetF(0, curFrameRect.Height());
2022 realStep = FocusStep::LEFT;
2023 } else if (step == FocusStep::SHIFT_TAB) {
2024 frameRect += OffsetF(0, curFrameRect.Height());
2025 realStep = FocusStep::RIGHT;
2026 }
2027 auto projectArea = GetProjectAreaOnRect(frameRect, curFrameRect, realStep);
2028 if (Positive(projectArea)) {
2029 OffsetF vec = frameRect.Center() - curFrameRect.Center();
2030 double val = (vec.GetX() * vec.GetX()) + (vec.GetY() * vec.GetY());
2031 if ((step == FocusStep::TAB && Positive(vec.GetX())) ||
2032 (step == FocusStep::SHIFT_TAB && Negative(vec.GetX()))) {
2033 val *= -1.0;
2034 }
2035 if ((!isTabStep && val < resDistance) || (isTabStep && val > resDistance)) {
2036 resDistance = val;
2037 nextNode = node;
2038 }
2039 }
2040 }
2041 TAG_LOGD(AceLogTag::ACE_FOCUS, "Next focus node is %{public}s/%{public}d. Min distance is %{public}f.",
2042 nextNode ? nextNode->GetFrameName().c_str() : "NULL", nextNode ? nextNode->GetFrameId() : -1, resDistance);
2043 return nextNode;
2044 }
2045
CloseKeyboard()2046 void FocusHub::CloseKeyboard()
2047 {
2048 #if defined(ENABLE_STANDARD_INPUT)
2049 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "CloseKeyBoard");
2050 auto inputMethod = MiscServices::InputMethodController::GetInstance();
2051 if (inputMethod) {
2052 inputMethod->Close();
2053 TAG_LOGI(AceLogTag::ACE_KEYBOARD, "CloseKeyBoard SoftKeyboard Closes Successfully.");
2054 }
2055 #endif
2056 }
2057 } // namespace OHOS::Ace::NG
2058