From e1103a4f4342122da0321ecd4ffec94e11f6e56d Mon Sep 17 00:00:00 2001 From: bixuefeng Date: Tue, 12 Mar 2024 10:07:48 +0800 Subject: [PATCH] =?UTF-8?q?Feature:=20=E5=B1=82=E7=BA=A7=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E8=B5=B0=E7=84=A6=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: bixuefeng Change-Id: I495a96742ee0bd6e724dbff3440b83ef866bce0a --- .../core/components_ng/base/frame_node.cpp | 10 +- .../core/components_ng/event/focus_hub.cpp | 295 ++++++------------ .../core/components_ng/event/focus_hub.h | 37 +-- .../core/components_ng/manager/BUILD.gn | 2 + .../manager/focus/focus_manager.cpp | 133 ++++++++ .../manager/focus/focus_manager.h | 60 ++++ .../manager/focus/focus_view.cpp | 256 +++++++++++++++ .../components_ng/manager/focus/focus_view.h | 89 ++++++ .../shared_transition_effect.cpp | 8 +- .../pattern/bubble/bubble_pattern.h | 11 +- .../pattern/dialog/dialog_pattern.h | 10 +- .../menu/menu_item/menu_item_pattern.cpp | 18 +- .../components_ng/pattern/menu/menu_pattern.h | 14 +- .../menu/wrapper/menu_wrapper_pattern.cpp | 7 +- .../pattern/navigation/nav_bar_pattern.h | 18 +- .../pattern/navigation/navigation_pattern.cpp | 43 ++- .../pattern/navigation/navigation_pattern.h | 9 +- .../navrouter/navdestination_pattern.h | 19 +- .../overlay/modal_presentation_pattern.h | 10 +- .../pattern/overlay/overlay_manager.cpp | 175 +---------- .../overlay/sheet_presentation_pattern.h | 10 +- .../pattern/stage/page_pattern.h | 9 +- .../pattern/stage/stage_manager.cpp | 25 +- .../scene/system_window_scene.cpp | 39 ++- .../window_scene/scene/system_window_scene.h | 12 +- .../window_scene/scene/window_scene.cpp | 1 - frameworks/core/event/key_event.h | 1 + .../core/pipeline_ng/pipeline_context.cpp | 119 +++---- .../core/pipeline_ng/pipeline_context.h | 23 +- .../core/pipeline/mock_pipeline_context.cpp | 2 - test/unittest/BUILD.gn | 2 + test/unittest/core/common/ace_engine/BUILD.gn | 2 + .../unittest/core/event/focus_hub_test_ng.cpp | 176 +---------- .../core/pattern/overlay/overlay_test_ng.cpp | 2 - test/unittest/core/pattern/plugin/BUILD.gn | 2 + .../pipeline/pipeline_context_test_ng.cpp | 73 +---- 36 files changed, 912 insertions(+), 810 deletions(-) create mode 100644 frameworks/core/components_ng/manager/focus/focus_manager.cpp create mode 100644 frameworks/core/components_ng/manager/focus/focus_manager.h create mode 100644 frameworks/core/components_ng/manager/focus/focus_view.cpp create mode 100644 frameworks/core/components_ng/manager/focus/focus_view.h diff --git a/frameworks/core/components_ng/base/frame_node.cpp b/frameworks/core/components_ng/base/frame_node.cpp index 17f135c2ccd..7b597cf05a1 100644 --- a/frameworks/core/components_ng/base/frame_node.cpp +++ b/frameworks/core/components_ng/base/frame_node.cpp @@ -856,8 +856,14 @@ void FrameNode::OnVisibleChange(bool isVisible) void FrameNode::OnDetachFromMainTree(bool recursive) { - if (auto focusHub = GetFocusHub()) { - focusHub->RemoveSelf(); + auto focusHub = GetFocusHub(); + if (focusHub) { + auto focusView = focusHub->GetFirstChildFocusView(); + if (focusView) { + focusView->FocusViewClose(); + } else { + focusHub->RemoveSelf(); + } } pattern_->OnDetachFromMainTree(); eventHub_->FireOnDisappear(); diff --git a/frameworks/core/components_ng/event/focus_hub.cpp b/frameworks/core/components_ng/event/focus_hub.cpp index a4ebc21407d..fec08a3832f 100644 --- a/frameworks/core/components_ng/event/focus_hub.cpp +++ b/frameworks/core/components_ng/event/focus_hub.cpp @@ -145,12 +145,15 @@ void FocusHub::DumpFocusNodeTree(int32_t depth) information += "(Node)"; } information += (" id:" + std::to_string(GetFrameId())); + information += (GetInspectorKey().has_value() ? " idstr:" + GetInspectorKey().value() : ""); if (!IsFocusable()) { information = "(-)" + information; - information += (" Enabled:" + std::to_string(IsEnabled()) + " Show:" + std::to_string(IsShow()) + - " Focusable:" + std::to_string(focusable_) + - " ParentFocusable:" + std::to_string(parentFocusable_)); + information += IsEnabled() ? "" : " Enabled:false"; + information += IsShow() ? "" : " Show:false"; + information += focusable_ ? "" : " Focusable:false"; + information += parentFocusable_ ? "" : " ParentFocusable:false"; } + information += IsDefaultFocus() ? "[Default]" : ""; DumpLog::GetInstance().Print(depth, information, 0); } } @@ -167,14 +170,15 @@ void FocusHub::DumpFocusScopeTree(int32_t depth) information += "(Scope)"; } information += (" id:" + std::to_string(GetFrameId())); + information += (GetInspectorKey().has_value() ? " idstr:" + GetInspectorKey().value() : ""); if (!IsFocusable()) { information = "(-)" + information; - if (!IsFocusableNode()) { - information += (" Enabled:" + std::to_string(IsEnabled()) + " Show:" + std::to_string(IsShow()) + - " Focusable:" + std::to_string(focusable_) + - " ParentFocusable:" + std::to_string(parentFocusable_)); - } + information += IsEnabled() ? "" : " Enabled:false"; + information += IsShow() ? "" : " Show:false"; + information += focusable_ ? "" : " Focusable:false"; + information += parentFocusable_ ? "" : " ParentFocusable:false"; } + information += IsDefaultFocus() ? "[Default]" : ""; DumpLog::GetInstance().Print(depth, information, static_cast(focusNodes.size())); } @@ -213,10 +217,10 @@ bool FocusHub::RequestFocusImmediately(bool isJudgeRootTree) auto parent = GetParentFocusHub(); if (parent) { - auto mainView = GetCurrentMainView(); - auto mainViewRootScope = mainView ? mainView->GetMainViewRootScope() : nullptr; - if (mainViewRootScope && parent == mainViewRootScope) { - mainView->SetIsViewRootScopeFocused(mainViewRootScope, false); + auto curFocusView = FocusView::GetCurrentFocusView(); + auto viewRootScope = curFocusView ? curFocusView->GetViewRootScope() : nullptr; + if (viewRootScope && parent == viewRootScope) { + curFocusView->SetIsViewRootScopeFocused(false); } parent->SwitchFocus(AceType::Claim(this)); } @@ -230,157 +234,25 @@ void FocusHub::UpdateAccessibilityFocusInfo() // Need update } -RefPtr FocusHub::GetChildMainView() -{ - std::list> children; - FlushChildrenFocusHub(children); - RefPtr curFocusMainView = nullptr; - RefPtr focusableMainView = nullptr; - for (const auto& child : children) { - if (!child) { - continue; - } - auto frameName = child->GetFrameName(); - if (frameName == V2::PAGE_ETS_TAG || frameName == V2::DIALOG_ETS_TAG || frameName == V2::MODAL_PAGE_TAG || - frameName == V2::MENU_ETS_TAG || frameName == V2::SHEET_PAGE_TAG || frameName == V2::POPUP_ETS_TAG || - frameName == V2::WINDOW_SCENE_ETS_TAG) { - if (!curFocusMainView && child->IsCurrentFocus() && child->IsFocusable()) { - curFocusMainView = child; - } - if (!focusableMainView && child->IsFocusable()) { - focusableMainView = child; - } - } - } - if (curFocusMainView) { - return curFocusMainView; - } - if (focusableMainView) { - return focusableMainView; - } - for (const auto& child : children) { - if (!child) { - continue; - } - auto result = child->GetChildMainView(); - if (result) { - return result; - } - } - return nullptr; -} - -RefPtr FocusHub::GetCurrentMainView() -{ - auto pipeline = PipelineContext::GetCurrentContextSafely(); - CHECK_NULL_RETURN(pipeline, nullptr); - auto screenNode = pipeline->GetScreenNode(); - if (screenNode) { - auto screenNodeFocusHub = screenNode->GetFocusHub(); - CHECK_NULL_RETURN(screenNodeFocusHub, nullptr); - return screenNodeFocusHub->GetChildMainView(); - } - auto rootNode = pipeline->GetRootElement(); - CHECK_NULL_RETURN(rootNode, nullptr); - auto rootFocusHub = rootNode->GetFocusHub(); - CHECK_NULL_RETURN(rootFocusHub, nullptr); - return rootFocusHub->GetChildMainView(); -} - -RefPtr FocusHub::GetMainViewRootScope() -{ - static const std::list DEEPTH_OF_MENU = { 0, 0 }; - static const std::list DEEPTH_OF_DIALOG = { 0, 0 }; - static const std::list DEEPTH_OF_PAGE = { 0 }; - static const std::list DEEPTH_OF_POPUP = { 0, 0 }; - static const std::list DEEPTH_OF_SHEET_PAGE = { 1, 0 }; - auto frameName = GetFrameName(); - std::list rootScopeDeepth; - if (frameName == V2::MENU_ETS_TAG) { - rootScopeDeepth = DEEPTH_OF_MENU; - } else if (frameName == V2::DIALOG_ETS_TAG) { - rootScopeDeepth = DEEPTH_OF_DIALOG; - } else if (frameName == V2::POPUP_ETS_TAG) { - rootScopeDeepth = DEEPTH_OF_POPUP; - } else if (frameName == V2::SHEET_PAGE_TAG) { - rootScopeDeepth = DEEPTH_OF_SHEET_PAGE; - } else { - rootScopeDeepth = DEEPTH_OF_PAGE; - } - RefPtr rootScope = AceType::Claim(this); - for (const auto& index : rootScopeDeepth) { - CHECK_NULL_RETURN(rootScope, nullptr); - auto children = rootScope->GetChildren(); - auto iter = children.begin(); - std::advance(iter, index); - if (iter == children.end()) { - TAG_LOGI(AceLogTag::ACE_FOCUS, "Index: %{public}d of %{public}s/%{public}d 's children is invalid.", index, - rootScope->GetFrameName().c_str(), rootScope->GetFrameId()); - return nullptr; - } - rootScope = *iter; - } - CHECK_NULL_RETURN(rootScope, nullptr); - if (rootScope->GetFocusType() != FocusType::SCOPE) { - return rootScope->GetParentFocusHub(); - } - return rootScope; -} - void FocusHub::LostFocusToViewRoot() { - auto mainView = GetCurrentMainView(); - CHECK_NULL_VOID(mainView); - auto mainViewRootScope = mainView->GetMainViewRootScope(); - CHECK_NULL_VOID(mainViewRootScope); + auto curFocusView = FocusView::GetCurrentFocusView(); + CHECK_NULL_VOID(curFocusView); + auto viewRootScope = curFocusView->GetViewRootScope(); + CHECK_NULL_VOID(viewRootScope); TAG_LOGD(AceLogTag::ACE_FOCUS, "Lost focus to view root: %{public}s/%{public}d", - mainViewRootScope->GetFrameName().c_str(), mainViewRootScope->GetFrameId()); - if (!mainViewRootScope->IsCurrentFocus()) { + viewRootScope->GetFrameName().c_str(), viewRootScope->GetFrameId()); + if (!viewRootScope->IsCurrentFocus()) { TAG_LOGI(AceLogTag::ACE_FOCUS, "View root: %{public}s/%{public}d is not on focusing.", - mainViewRootScope->GetFrameName().c_str(), mainViewRootScope->GetFrameId()); + viewRootScope->GetFrameName().c_str(), viewRootScope->GetFrameId()); return; } - mainView->SetIsViewRootScopeFocused(mainViewRootScope, true); - auto focusedChild = mainViewRootScope->lastWeakFocusNode_.Upgrade(); + curFocusView->SetIsViewRootScopeFocused(true); + auto focusedChild = viewRootScope->lastWeakFocusNode_.Upgrade(); CHECK_NULL_VOID(focusedChild); focusedChild->LostFocus(); } -bool FocusHub::HandleFocusOnMainView() -{ - auto viewRootScope = GetMainViewRootScope(); - CHECK_NULL_RETURN(viewRootScope, false); - if (!viewRootScope->IsCurrentFocus()) { - TAG_LOGI(AceLogTag::ACE_FOCUS, - "Current view root: %{public}s/%{public}d is not on focusing. Cannot handle focus.", - viewRootScope->GetFrameName().c_str(), viewRootScope->GetFrameId()); - return false; - } - if (viewRootScope->GetFocusDependence() != FocusDependence::SELF) { - TAG_LOGI(AceLogTag::ACE_FOCUS, - "Current view root: %{public}s/%{public}d is not focus depend self. Do not need handle focus.", - viewRootScope->GetFrameName().c_str(), viewRootScope->GetFrameId()); - return false; - } - - TabIndexNodeList tabIndexNodes; - tabIndexNodes.clear(); - CollectTabIndexNodes(tabIndexNodes); - if (tabIndexNodes.empty()) { - // No tabIndex node in current main view. Extend focus from viewRootScope to children. - SetIsDefaultHasFocused(true); - SetIsViewRootScopeFocused(viewRootScope, false); - viewRootScope->OnFocusScope(true); - return true; - } - - // First tabIndex node need get focus. - tabIndexNodes.sort([](std::pair>& a, std::pair>& b) { - return a.first < b.first; - }); - return GoToFocusByTabNodeIdx(tabIndexNodes, 0); -} - void FocusHub::LostFocus(BlurReason reason) { TAG_LOGD(AceLogTag::ACE_FOCUS, "Node %{public}s/%{public}d lost focus. Lost reason: %{public}d.", @@ -403,12 +275,14 @@ void FocusHub::LostSelfFocus() void FocusHub::RemoveSelf(BlurReason reason) { - TAG_LOGD(AceLogTag::ACE_FOCUS, "Node %{public}s/%{public}d remove self.", GetFrameName().c_str(), GetFrameId()); + TAG_LOGD(AceLogTag::ACE_FOCUS, "%{public}s/%{public}d remove self focus.", GetFrameName().c_str(), GetFrameId()); + auto frameNode = GetFrameNode(); + auto focusView = frameNode ? frameNode->GetPattern() : nullptr; auto pipeline = PipelineContext::GetCurrentContext(); auto screenNode = pipeline ? pipeline->GetScreenNode() : nullptr; auto screenFocusHub = screenNode ? screenNode->GetFocusHub() : nullptr; auto parent = GetParentFocusHub(); - if (parent && parent != screenFocusHub) { + if (parent && parent != screenFocusHub && !focusView) { parent->RemoveChild(AceType::Claim(this), reason); } else { LostFocus(reason); @@ -429,10 +303,10 @@ void FocusHub::RemoveChild(const RefPtr& focusNode, BlurReason reason) // Try to goto next focus, otherwise goto previous focus. if (!GoToNextFocusLinear(FocusStep::TAB) && !GoToNextFocusLinear(FocusStep::SHIFT_TAB)) { lastWeakFocusNode_ = nullptr; - auto mainView = GetCurrentMainView(); - auto mainViewRootScope = mainView ? mainView->GetMainViewRootScope() : nullptr; + auto focusView = FocusView::GetCurrentFocusView(); + auto mainViewRootScope = focusView ? focusView->GetViewRootScope() : nullptr; if (mainViewRootScope && mainViewRootScope == AceType::Claim(this)) { - mainView->SetIsViewRootScopeFocused(mainViewRootScope, true); + focusView->SetIsViewRootScopeFocused(true); } else { RemoveSelf(reason); } @@ -765,12 +639,18 @@ bool FocusHub::OnKeyEventScope(const KeyEvent& keyEvent) return RequestNextFocus(FocusStep::RIGHT, GetRect()); case KeyCode::KEY_TAB: { auto context = NG::PipelineContext::GetCurrentContext(); + CHECK_NULL_RETURN(context, false); + auto curFocusView = FocusView::GetCurrentFocusView(); + auto entryFocusView = curFocusView ? curFocusView->GetEntryFocusView() : nullptr; + auto entryFocusViewHub = entryFocusView ? entryFocusView->GetFocusHub() : nullptr; + auto focusParent = GetParentFocusHub(); + bool isCurrentHandledByFocusView = + (entryFocusViewHub && entryFocusViewHub == this) || !focusParent || !focusParent->IsCurrentFocus(); bool ret = false; if (keyEvent.pressedCodes.size() == 1) { context->SetIsFocusingByTab(true); ret = RequestNextFocus(FocusStep::TAB, GetRect()); - auto focusParent = GetParentFocusHub(); - if (!focusParent || !focusParent->IsCurrentFocus()) { + if (!ret && isCurrentHandledByFocusView) { if (context->IsFocusWindowIdSetted()) { FocusToHeadOrTailChild(true); return false; @@ -781,8 +661,7 @@ bool FocusHub::OnKeyEventScope(const KeyEvent& keyEvent) } else if (keyEvent.IsShiftWith(KeyCode::KEY_TAB)) { context->SetIsFocusingByTab(true); ret = RequestNextFocus(FocusStep::SHIFT_TAB, GetRect()); - auto focusParent = GetParentFocusHub(); - if (!focusParent || !focusParent->IsCurrentFocus()) { + if (!ret && isCurrentHandledByFocusView) { if (context->IsFocusWindowIdSetted()) { FocusToHeadOrTailChild(false); return false; @@ -813,35 +692,6 @@ void FocusHub::RequestFocus() const context->AddDirtyFocus(GetFrameNode()); } -void FocusHub::RequestFocusWithDefaultFocusFirstly() -{ - TAG_LOGD(AceLogTag::ACE_FOCUS, "Request focus with default focus on node: %{public}s/%{public}d.", - GetFrameName().c_str(), GetFrameId()); - auto pipeline = PipelineContext::GetCurrentContextSafely(); - CHECK_NULL_VOID(pipeline); - - RefPtr viewScope; - if (GetFrameName() == V2::MENU_WRAPPER_ETS_TAG) { - viewScope = GetChildren().front(); - } else { - viewScope = Claim(this); - } - if (!viewScope) { - pipeline->AddDirtyDefaultFocus(GetFrameNode()); - return; - } - - auto screenNode = pipeline->GetScreenNode(); - if (!screenNode || viewScope->GetFrameName() != V2::PAGE_ETS_TAG) { - auto viewRootScope = viewScope->GetMainViewRootScope(); - if (viewRootScope && viewScope->GetIsViewRootScopeFocused()) { - viewRootScope->SetFocusDependence(FocusDependence::SELF); - } - } - - pipeline->AddDirtyDefaultFocus(viewScope->GetFrameNode()); -} - bool FocusHub::RequestNextFocus(FocusStep moveStep, const RectF& rect) { TAG_LOGI(AceLogTag::ACE_FOCUS, "Request next focus on node: %{public}s/%{public}d by step: %{public}d.", @@ -1104,6 +954,7 @@ void FocusHub::OnFocus() CHECK_NULL_VOID(frameNode); auto curPattern = frameNode->GetPattern(); CHECK_NULL_VOID(curPattern); + UpdateFocusView(); bool isNeedKeyboard = curPattern->NeedSoftKeyboard(); auto pipeline = PipelineContext::GetCurrentContextSafely(); CHECK_NULL_VOID(pipeline); @@ -1797,6 +1648,17 @@ RefPtr FocusHub::GetChildFocusNodeByType(FocusNodeType nodeType) std::list> focusNodes; FlushChildrenFocusHub(focusNodes); for (const auto& child : focusNodes) { + if (!child) { + continue; + } + auto childFrame = child->GetFrameNode(); + if (!childFrame) { + continue; + } + auto childFocusView = childFrame->GetPattern(); + if (childFocusView && childFocusView->IsFocusViewLegal()) { + continue; + } auto findNode = child->GetChildFocusNodeByType(nodeType); if (findNode) { return findNode; @@ -1826,6 +1688,29 @@ RefPtr FocusHub::GetChildFocusNodeById(const std::string& id) return nullptr; } +RefPtr FocusHub::GetFirstChildFocusView() +{ + auto frameNode = GetFrameNode(); + CHECK_NULL_RETURN(frameNode, nullptr); + auto focusView = frameNode->GetPattern(); + if (focusView) { + return focusView; + } + std::list> children; + FlushChildrenFocusHub(children); + for (auto iter = children.rbegin(); iter != children.rend(); ++iter) { + auto childFocusHub = *iter; + if (!childFocusHub) { + continue; + } + auto childResult = childFocusHub->GetFirstChildFocusView(); + if (childResult) { + return childResult; + } + } + return nullptr; +} + void FocusHub::HandleParentScroll() const { auto context = PipelineContext::GetCurrentContext(); @@ -2060,6 +1945,34 @@ RefPtr FocusHub::GetNearestNodeByProjectArea(const std::listGetPattern(); + CHECK_NULL_RETURN(focusView, false); + auto focusedChild = lastWeakFocusNode_.Upgrade(); + while (focusedChild) { + auto focusedChildFrame = focusedChild->GetFrameNode(); + if (!focusedChildFrame) { + focusedChild = focusedChild->lastWeakFocusNode_.Upgrade(); + continue; + } + auto focusedChildFocusView = focusedChildFrame->GetPattern(); + if (focusedChildFocusView) { + return false; + } + focusedChild = focusedChild->lastWeakFocusNode_.Upgrade(); + } + auto curFocusView = FocusView::GetCurrentFocusView(); + if (focusView && focusView->IsFocusViewLegal() && focusView != curFocusView) { + focusView->SetIsViewRootScopeFocused(false); + focusView->FocusViewShow(); + } + return true; +} + void FocusHub::CloseKeyboard() { #if defined(ENABLE_STANDARD_INPUT) diff --git a/frameworks/core/components_ng/event/focus_hub.h b/frameworks/core/components_ng/event/focus_hub.h index 2240cdd5fb8..09d7f29ed65 100644 --- a/frameworks/core/components_ng/event/focus_hub.h +++ b/frameworks/core/components_ng/event/focus_hub.h @@ -27,6 +27,7 @@ namespace OHOS::Ace::NG { class FrameNode; class FocusHub; class EventHub; +class FocusView; using TabIndexNodeList = std::list>>; constexpr int32_t DEFAULT_TAB_FOCUSED_INDEX = -2; @@ -642,23 +643,21 @@ public: bool HandleKeyEvent(const KeyEvent& keyEvent); bool RequestFocusImmediately(bool isJudgeRootTree = false); void RequestFocus() const; - void RequestFocusWithDefaultFocusFirstly(); void UpdateAccessibilityFocusInfo(); void SwitchFocus(const RefPtr& focusNode); - RefPtr GetChildMainView(); - RefPtr GetMainViewRootScope(); - - static RefPtr GetCurrentMainView(); static void LostFocusToViewRoot(); - bool HandleFocusOnMainView(); void LostFocus(BlurReason reason = BlurReason::FOCUS_SWITCH); void LostSelfFocus(); void RemoveSelf(BlurReason reason = BlurReason::FRAME_DESTROY); void RemoveChild(const RefPtr& focusNode, BlurReason reason = BlurReason::FRAME_DESTROY); bool GoToNextFocusLinear(FocusStep step, const RectF& rect = RectF()); bool TryRequestFocus(const RefPtr& focusNode, const RectF& rect, FocusStep step = FocusStep::NONE); + void InheritFocus() + { + OnFocusScope(true); + } void CollectTabIndexNodes(TabIndexNodeList& tabIndexNodes); bool GoToFocusByTabNodeIdx(TabIndexNodeList& tabIndexNodes, int32_t tabNodeIdx); @@ -668,6 +667,7 @@ public: void HandleParentScroll() const; int32_t GetFocusingTabNodeIdx(TabIndexNodeList& tabIndexNodes) const; bool RequestFocusImmediatelyById(const std::string& id); + RefPtr GetFirstChildFocusView(); bool IsFocusableByTab(); bool IsFocusableNodeByTab(); @@ -986,18 +986,6 @@ public: return focusCallbackEvents_ ? focusCallbackEvents_->IsDefaultGroupHasFocused() : false; } - void SetIsViewRootScopeFocused(const RefPtr& viewRootScope, bool isViewRootScopeFocused) - { - isViewRootScopeFocused_ = isViewRootScopeFocused; - if (viewRootScope) { - viewRootScope->SetFocusDependence(isViewRootScopeFocused ? FocusDependence::SELF : FocusDependence::AUTO); - } - } - bool GetIsViewRootScopeFocused() const - { - return isViewRootScopeFocused_; - } - bool IsImplicitFocusableScope() const { return (focusType_ == FocusType::SCOPE) && focusable_ && implicitFocusable_; @@ -1039,15 +1027,6 @@ public: focusDepend_ = focusDepend; } - void SetIsViewHasFocused(bool isViewHasFocused) - { - isViewHasFocused_ = isViewHasFocused; - } - bool GetIsViewHasFocused() const - { - return isViewHasFocused_; - } - size_t GetFocusableCount() { size_t count = 0; @@ -1131,6 +1110,8 @@ private: RefPtr GetNearestNodeByProjectArea(const std::list>& allNodes, FocusStep step); + bool UpdateFocusView(); + OnFocusFunc onFocusInternal_; OnBlurFunc onBlurInternal_; OnBlurReasonFunc onBlurReasonInternal_; @@ -1155,8 +1136,6 @@ private: bool parentFocusable_ { true }; bool currentFocus_ { false }; bool isFocusUnit_ { false }; - bool isViewRootScopeFocused_ { true }; - bool isViewHasFocused_ { false }; bool hasForwardMovement_ { false }; bool hasBackwardMovement_ { false }; bool isFocusActiveWhenFocused_ { false }; diff --git a/frameworks/core/components_ng/manager/BUILD.gn b/frameworks/core/components_ng/manager/BUILD.gn index c106bb024a2..4bc02592b7d 100644 --- a/frameworks/core/components_ng/manager/BUILD.gn +++ b/frameworks/core/components_ng/manager/BUILD.gn @@ -20,6 +20,8 @@ build_component_ng("manager_ng") { "display_sync/ui_display_sync_manager.cpp", "drag_drop/drag_drop_manager.cpp", "drag_drop/drag_drop_proxy.cpp", + "focus/focus_manager.cpp", + "focus/focus_view.cpp", "frame_rate/frame_rate_manager.cpp", "full_screen/full_screen_manager.cpp", "navigation_dump/navigation_dump_manager.cpp", diff --git a/frameworks/core/components_ng/manager/focus/focus_manager.cpp b/frameworks/core/components_ng/manager/focus/focus_manager.cpp new file mode 100644 index 00000000000..c625a690f1e --- /dev/null +++ b/frameworks/core/components_ng/manager/focus/focus_manager.cpp @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "core/components_ng/manager/focus/focus_manager.h" + +#include "base/log/dump_log.h" +#include "base/log/log_wrapper.h" +#include "base/memory/ace_type.h" +#include "base/memory/referenced.h" +#include "base/utils/utils.h" +#include "core/components_ng/pattern/pattern.h" + +namespace OHOS::Ace::NG { + +void FocusManager::FocusViewShow(const RefPtr& focusView) +{ + CHECK_NULL_VOID(focusView); + auto lastFocusView = lastFocusView_.Upgrade(); + if (lastFocusView) { + if (lastFocusView == focusView) { + return; + } + lastFocusView->LostViewFocus(); + } + + auto focusViewWeak = AceType::WeakClaim(AceType::RawPtr(focusView)); + if (std::find(focusViewStack_.begin(), focusViewStack_.end(), focusViewWeak) != focusViewStack_.end()) { + focusViewStack_.remove(focusViewWeak); + } + focusViewStack_.emplace_back(focusViewWeak); + lastFocusView_ = focusViewWeak; +} + +void FocusManager::FocusViewHide(const RefPtr& focusView) +{ + CHECK_NULL_VOID(focusView); + auto lastFocusView = lastFocusView_.Upgrade(); + if (lastFocusView && lastFocusView == focusView) { + lastFocusView->LostViewFocus(); + lastFocusView_ = nullptr; + } +} + +void FocusManager::FocusViewClose(const RefPtr& focusView) +{ + CHECK_NULL_VOID(focusView); + auto lastFocusView = lastFocusView_.Upgrade(); + if (lastFocusView && lastFocusView == focusView) { + lastFocusView->LostViewFocus(); + } + auto focusViewWeak = AceType::WeakClaim(AceType::RawPtr(focusView)); + if (std::find(focusViewStack_.begin(), focusViewStack_.end(), focusViewWeak) != focusViewStack_.end()) { + focusViewStack_.remove(focusViewWeak); + } + if (focusViewStack_.back() != lastFocusView_) { + lastFocusView_ = focusViewStack_.back(); + } +} + +void FocusManager::GetFocusViewMap(FocusViewMap& focusViewMap) +{ + for (const auto& focusViewWeak : focusViewStack_) { + auto focusView = focusViewWeak.Upgrade(); + if (!focusView) { + continue; + } + auto focusViewId = focusView->GetFrameId(); + auto entryFocusView = focusView->GetEntryFocusView(); + if (entryFocusView && entryFocusView != focusView) { + auto entryFocusViewId = entryFocusView->GetFrameId(); + auto entryFocusViewWeak = AceType::WeakClaim(AceType::RawPtr(entryFocusView)); + auto iter = focusViewMap.find(entryFocusViewId); + if (iter == focusViewMap.end()) { + focusViewMap[entryFocusViewId] = { entryFocusViewWeak, { focusViewWeak } }; + } else { + iter->second.second.emplace_back(focusViewWeak); + } + } else { + focusViewMap[focusViewId] = { focusViewWeak, {} }; + } + } +} + +void FocusManager::DumpFocusManager() +{ + if (!DumpLog::GetInstance().GetDumpFile()) { + return; + } + DumpLog::GetInstance().Print("Focus view:"); + std::unordered_map, std::list>>> focusViewMap; + GetFocusViewMap(focusViewMap); + for (const auto& focusViewInfo : focusViewMap) { + auto focusView = focusViewInfo.second.first.Upgrade(); + if (!focusView) { + continue; + } + auto childFocusViewWeakList = focusViewInfo.second.second; + bool isFocusedView = false; + auto lastFocusView = lastFocusView_.Upgrade(); + auto lastEntryFocusView = lastFocusView ? lastFocusView->GetEntryFocusView() : nullptr; + if (focusView == lastEntryFocusView) { + isFocusedView = true; + } + std::string information = focusView->GetFrameName(); + information += isFocusedView ? "(*)" : ""; + information += " id:" + std::to_string(focusView->GetFrameId()); + DumpLog::GetInstance().Print(0, information, static_cast(childFocusViewWeakList.size())); + for (const auto& childWeak : childFocusViewWeakList) { + auto child = childWeak.Upgrade(); + if (!child) { + continue; + } + std::string childInformation = child->GetFrameName(); + childInformation += child == lastFocusView ? "(*)" : ""; + childInformation += " id:" + std::to_string(child->GetFrameId()); + DumpLog::GetInstance().Print(1, childInformation, 0); + } + } +} + +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/manager/focus/focus_manager.h b/frameworks/core/components_ng/manager/focus/focus_manager.h new file mode 100644 index 00000000000..c47e0f128ee --- /dev/null +++ b/frameworks/core/components_ng/manager/focus/focus_manager.h @@ -0,0 +1,60 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_MANAGER_FOCUS_FOCUS_MANAGER_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_MANAGER_FOCUS_FOCUS_MANAGER_H + +#include + +#include "base/memory/ace_type.h" +#include "base/memory/referenced.h" +#include "core/components_ng/manager/focus/focus_view.h" + +namespace OHOS::Ace::NG { + +using FocusViewMap = std::unordered_map, std::list>>>; + +class FocusManager : public virtual AceType { + DECLARE_ACE_TYPE(FocusManager, AceType); + +public: + FocusManager() + { + focusViewStack_.clear(); + } + ~FocusManager() override = default; + + void FocusViewShow(const RefPtr& focusView); + void FocusViewHide(const RefPtr& focusView); + void FocusViewClose(const RefPtr& focusView); + + void DumpFocusManager(); + + WeakPtr GetLastFocusView() const + { + return lastFocusView_; + } + +private: + void GetFocusViewMap(FocusViewMap& focusViewMap); + + std::list> focusViewStack_; + WeakPtr lastFocusView_; + + ACE_DISALLOW_COPY_AND_MOVE(FocusManager); +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_MANAGER_FOCUS_FOCUS_MANAGER_H diff --git a/frameworks/core/components_ng/manager/focus/focus_view.cpp b/frameworks/core/components_ng/manager/focus/focus_view.cpp new file mode 100644 index 00000000000..03293509608 --- /dev/null +++ b/frameworks/core/components_ng/manager/focus/focus_view.cpp @@ -0,0 +1,256 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include "core/components_ng/manager/focus/focus_view.h" + +#include "base/memory/ace_type.h" +#include "base/memory/referenced.h" +#include "core/event/key_event.h" +#include "core/pipeline_ng/pipeline_context.h" + +namespace OHOS::Ace::NG { + +void FocusView::FocusViewShow() +{ + TAG_LOGI(AceLogTag::ACE_FOCUS, "Focus view: %{public}s/%{public}d show", GetFrameName().c_str(), GetFrameId()); + auto viewRootScope = GetViewRootScope(); + if (viewRootScope && GetIsViewRootScopeFocused()) { + viewRootScope->SetFocusDependence(FocusDependence::SELF); + } + isViewHasFocused_ = false; + auto pipeline = PipelineContext::GetCurrentContext(); + CHECK_NULL_VOID(pipeline); + auto focusManager = pipeline->GetFocusManager(); + CHECK_NULL_VOID(focusManager); + focusManager->FocusViewShow(AceType::Claim(this)); + pipeline->RequestFrame(); +} + +void FocusView::FocusViewHide() +{ + TAG_LOGI(AceLogTag::ACE_FOCUS, "Focus view: %{public}s/%{public}d hide", GetFrameName().c_str(), GetFrameId()); + auto pipeline = PipelineContext::GetCurrentContext(); + CHECK_NULL_VOID(pipeline); + auto focusManager = pipeline->GetFocusManager(); + CHECK_NULL_VOID(focusManager); + focusManager->FocusViewHide(AceType::Claim(this)); + pipeline->RequestFrame(); +} + +void FocusView::FocusViewClose() +{ + TAG_LOGI(AceLogTag::ACE_FOCUS, "Focus view: %{public}s/%{public}d close", GetFrameName().c_str(), GetFrameId()); + auto pipeline = PipelineContext::GetCurrentContext(); + CHECK_NULL_VOID(pipeline); + auto focusManager = pipeline->GetFocusManager(); + CHECK_NULL_VOID(focusManager); + focusManager->FocusViewClose(AceType::Claim(this)); + pipeline->RequestFrame(); +} + +RefPtr FocusView::GetFrameNode() +{ + auto focusViewPattern = AceType::DynamicCast(AceType::Claim(this)); + CHECK_NULL_RETURN(focusViewPattern, nullptr); + return focusViewPattern->GetHost(); +} + +std::string FocusView::GetFrameName() +{ + auto focusViewPattern = AceType::DynamicCast(AceType::Claim(this)); + CHECK_NULL_RETURN(focusViewPattern, "NULL"); + auto focusViewFrame = focusViewPattern->GetHost(); + CHECK_NULL_RETURN(focusViewFrame, "NULL"); + return focusViewFrame->GetTag(); +} + +int32_t FocusView::GetFrameId() +{ + auto focusViewPattern = AceType::DynamicCast(AceType::Claim(this)); + CHECK_NULL_RETURN(focusViewPattern, -1); + auto focusViewFrame = focusViewPattern->GetHost(); + CHECK_NULL_RETURN(focusViewFrame, -1); + return focusViewFrame->GetId(); +} + +void FocusView::LostViewFocus() +{ + TAG_LOGI( + AceLogTag::ACE_FOCUS, "Focus view: %{public}s/%{public}d lost focus", GetFrameName().c_str(), GetFrameId()); + auto focusViewHub = GetFocusHub(); + CHECK_NULL_VOID(focusViewHub); + focusViewHub->LostFocus(BlurReason::VIEW_SWITCH); +} + +RefPtr FocusView::GetFocusHub() +{ + auto focusViewPattern = AceType::DynamicCast(AceType::Claim(this)); + CHECK_NULL_RETURN(focusViewPattern, nullptr); + auto focusViewFrame = focusViewPattern->GetHost(); + CHECK_NULL_RETURN(focusViewFrame, nullptr); + auto focusViewHub = focusViewFrame->GetFocusHub(); + return focusViewHub; +} + +RefPtr FocusView::GetCurrentFocusView() +{ + auto pipeline = PipelineContext::GetCurrentContext(); + CHECK_NULL_RETURN(pipeline, nullptr); + auto focusManager = pipeline->GetFocusManager(); + CHECK_NULL_RETURN(focusManager, nullptr); + return focusManager->GetLastFocusView().Upgrade(); +} + +RefPtr FocusView::GetEntryFocusView() +{ + auto entryFocusViewName = GetEntryFocusViewName(); + if (entryFocusViewName.empty()) { + return AceType::Claim(this); + } + RefPtr result = AceType::Claim(this); + auto focusViewHub = GetFocusHub(); + auto parentFocusHub = focusViewHub ? focusViewHub->GetParentFocusHub() : nullptr; + while (parentFocusHub) { + auto parentFrame = parentFocusHub->GetFrameNode(); + auto parentFocusView = parentFrame ? parentFrame->GetPattern() : nullptr; + if (parentFocusView && parentFocusView->GetFrameName() == entryFocusViewName) { + result = parentFocusView; + } + parentFocusHub = parentFocusHub->GetParentFocusHub(); + } + return result; +} + +RefPtr FocusView::GetViewRootScope() +{ + auto focusViewPattern = AceType::DynamicCast(AceType::Claim(this)); + CHECK_NULL_RETURN(focusViewPattern, nullptr); + auto focusViewFrame = focusViewPattern->GetHost(); + CHECK_NULL_RETURN(focusViewFrame, nullptr); + auto focusViewHub = focusViewFrame->GetFocusHub(); + CHECK_NULL_RETURN(focusViewHub, nullptr); + std::list rootScopeDeepth = GetRouteOfFirstScope(); + RefPtr rootScope = focusViewHub; + for (const auto& index : rootScopeDeepth) { + CHECK_NULL_RETURN(rootScope, focusViewHub); + auto children = rootScope->GetChildren(); + auto iter = children.begin(); + std::advance(iter, index); + if (iter == children.end()) { + TAG_LOGI(AceLogTag::ACE_FOCUS, "Index: %{public}d of %{public}s/%{public}d 's children is invalid.", index, + rootScope->GetFrameName().c_str(), rootScope->GetFrameId()); + return focusViewHub; + } + rootScope = *iter; + } + CHECK_NULL_RETURN(rootScope, nullptr); + auto pipeline = PipelineContext::GetCurrentContext(); + auto screenNode = pipeline ? pipeline->GetScreenNode() : nullptr; + auto screenFocusHub = screenNode ? screenNode->GetFocusHub() : nullptr; + if (rootScope->GetFocusType() != FocusType::SCOPE || (screenFocusHub && rootScope == screenFocusHub)) { + return rootScope->GetParentFocusHub(); + } + return rootScope; +} + +void FocusView::SetIsViewRootScopeFocused(bool isViewRootScopeFocused) +{ + isViewRootScopeFocused_ = isViewRootScopeFocused; + auto viewRootScope = GetViewRootScope(); + CHECK_NULL_VOID(viewRootScope); + viewRootScope->SetFocusDependence(isViewRootScopeFocused ? FocusDependence::SELF : FocusDependence::AUTO); +} + +bool FocusView::IsRootScopeCurrentFocus() +{ + auto viewRootScope = GetViewRootScope(); + return viewRootScope ? viewRootScope->IsCurrentFocus() : false; +} + +bool FocusView::RequestDefaultFocus() +{ + TAG_LOGI(AceLogTag::ACE_FOCUS, "Request focus on focus view: %{public}s/%{public}d.", GetFrameName().c_str(), + GetFrameId()); + auto focusViewHub = GetFocusHub(); + CHECK_NULL_RETURN(focusViewHub, false); + if (focusViewHub->GetFocusType() != FocusType::SCOPE || !focusViewHub->IsFocusableNode()) { + return false; + } + isViewHasFocused_ = true; + auto viewRootScope = GetViewRootScope(); + auto defaultFocusNode = focusViewHub->GetChildFocusNodeByType(FocusNodeType::DEFAULT); + if (!defaultFocusNode) { + TAG_LOGI(AceLogTag::ACE_FOCUS, "Focus view has no default focus."); + } + if (!isDefaultHasBeFocused_ && defaultFocusNode && defaultFocusNode->IsFocusableWholePath()) { + SetIsViewRootScopeFocused(false); + auto ret = defaultFocusNode->RequestFocusImmediately(); + isDefaultHasBeFocused_ = true; + TAG_LOGI(AceLogTag::ACE_FOCUS, "Request focus on default focus: %{public}s/%{public}d return: %{public}d.", + defaultFocusNode->GetFrameName().c_str(), defaultFocusNode->GetFrameId(), ret); + return ret; + } + if (isViewRootScopeFocused_ && viewRootScope) { + SetIsViewRootScopeFocused(true); + auto ret = viewRootScope->RequestFocusImmediately(); + TAG_LOGI(AceLogTag::ACE_FOCUS, "Request focus on view root scope: %{public}s/%{public}d return: %{public}d.", + viewRootScope->GetFrameName().c_str(), viewRootScope->GetFrameId(), ret); + return ret; + } + SetIsViewRootScopeFocused(false); + auto ret = focusViewHub->RequestFocusImmediately(); + TAG_LOGI(AceLogTag::ACE_FOCUS, "Request focus on focus view return: %{public}d.", ret); + return ret; +} + +bool FocusView::TriggerFocusMove() +{ + TAG_LOGI(AceLogTag::ACE_FOCUS, "Focus view: %{public}s/%{public}d trigger focus move.", GetFrameName().c_str(), + GetFrameId()); + auto viewRootScope = GetViewRootScope(); + CHECK_NULL_RETURN(viewRootScope, false); + if (!viewRootScope->IsCurrentFocus()) { + TAG_LOGI(AceLogTag::ACE_FOCUS, + "Current view root: %{public}s/%{public}d is not on focusing. Cannot trigger focus move.", + viewRootScope->GetFrameName().c_str(), viewRootScope->GetFrameId()); + return false; + } + if (viewRootScope->GetFocusDependence() != FocusDependence::SELF) { + TAG_LOGI(AceLogTag::ACE_FOCUS, + "Current view root: %{public}s/%{public}d is not focus depend self. Do not trigger focus move.", + viewRootScope->GetFrameName().c_str(), viewRootScope->GetFrameId()); + return false; + } + + auto viewFocusHub = GetFocusHub(); + CHECK_NULL_RETURN(viewFocusHub, false); + TabIndexNodeList tabIndexNodes; + tabIndexNodes.clear(); + viewFocusHub->CollectTabIndexNodes(tabIndexNodes); + if (tabIndexNodes.empty()) { + // No tabIndex node in current main view. Extend focus from viewRootScope to children. + isDefaultHasBeFocused_ = true; + SetIsViewRootScopeFocused(false); + viewRootScope->InheritFocus(); + return true; + } + + // First tabIndex node need get focus. + tabIndexNodes.sort([](std::pair>& a, std::pair>& b) { + return a.first < b.first; + }); + return viewFocusHub->GoToFocusByTabNodeIdx(tabIndexNodes, 0); +} +} // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/manager/focus/focus_view.h b/frameworks/core/components_ng/manager/focus/focus_view.h new file mode 100644 index 00000000000..3222fb836c7 --- /dev/null +++ b/frameworks/core/components_ng/manager/focus/focus_view.h @@ -0,0 +1,89 @@ +/* + * Copyright (c) 2024 Huawei Device Co., Ltd. + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_MANAGER_FOCUS_FOCUS_VIEW_H +#define FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_MANAGER_FOCUS_FOCUS_VIEW_H + +#include + +#include "base/memory/ace_type.h" +#include "base/memory/referenced.h" +#include "base/utils/utils.h" +#include "core/components_ng/event/focus_hub.h" + +namespace OHOS::Ace::NG { + +class FocusView : public virtual AceType { + DECLARE_ACE_TYPE(FocusView, AceType); + +public: + FocusView() = default; + ~FocusView() override = default; + + virtual std::list GetRouteOfFirstScope() = 0; + virtual std::string GetEntryFocusViewName() + { + return std::string(); + } + virtual bool IsFocusViewLegal() + { + return true; + } + + RefPtr GetFrameNode(); + std::string GetFrameName(); + int32_t GetFrameId(); + + void FocusViewShow(); + void FocusViewHide(); + void FocusViewClose(); + + virtual void LostViewFocus(); + + RefPtr GetFocusHub(); + + static RefPtr GetCurrentFocusView(); + RefPtr GetEntryFocusView(); + RefPtr GetViewRootScope(); + bool IsRootScopeCurrentFocus(); + + bool RequestDefaultFocus(); + bool TriggerFocusMove(); + + void SetIsViewRootScopeFocused(bool isViewRootScopeFocused); + bool GetIsViewRootScopeFocused() const + { + return isViewRootScopeFocused_; + } + + void SetIsViewHasFocused(bool isViewHasFocused) + { + isViewHasFocused_ = isViewHasFocused; + } + bool GetIsViewHasFocused() const + { + return isViewHasFocused_; + } + +private: + bool isDefaultHasBeFocused_ = false; + bool isViewRootScopeFocused_ = true; + bool isViewHasFocused_ = false; + + ACE_DISALLOW_COPY_AND_MOVE(FocusView); +}; +} // namespace OHOS::Ace::NG + +#endif // FOUNDATION_ACE_FRAMEWORKS_CORE_COMPONENTS_NG_MANAGER_FOCUS_FOCUS_VIEW_H diff --git a/frameworks/core/components_ng/manager/shared_overlay/shared_transition_effect.cpp b/frameworks/core/components_ng/manager/shared_overlay/shared_transition_effect.cpp index 5646e402f7b..a3f96af87b6 100644 --- a/frameworks/core/components_ng/manager/shared_overlay/shared_transition_effect.cpp +++ b/frameworks/core/components_ng/manager/shared_overlay/shared_transition_effect.cpp @@ -21,6 +21,7 @@ #include "core/components/common/properties/motion_path_evaluator.h" #include "core/components_ng/base/frame_node.h" #include "core/components_ng/layout/layout_property.h" +#include "core/components_ng/pattern/stage/page_pattern.h" #include "core/components_ng/property/property.h" namespace OHOS::Ace::NG { @@ -252,10 +253,9 @@ void SharedTransitionExchange::DestRequestDefaultFocus() CHECK_NULL_VOID(dest); auto page = dest->GetPageNode(); CHECK_NULL_VOID(page); - auto pageFocusHub = page->GetFocusHub(); - CHECK_NULL_VOID(pageFocusHub); - pageFocusHub->SetParentFocusable(true); - pageFocusHub->RequestFocusWithDefaultFocusFirstly(); + auto pagePattern = page->GetPattern(); + CHECK_NULL_VOID(pagePattern); + pagePattern->FocusViewShow(); } SharedTransitionStatic::SharedTransitionStatic( diff --git a/frameworks/core/components_ng/pattern/bubble/bubble_pattern.h b/frameworks/core/components_ng/pattern/bubble/bubble_pattern.h index 55329fc0a79..70ab886a97d 100644 --- a/frameworks/core/components_ng/pattern/bubble/bubble_pattern.h +++ b/frameworks/core/components_ng/pattern/bubble/bubble_pattern.h @@ -24,6 +24,7 @@ #include "core/components/popup/popup_theme.h" #include "core/components_ng/base/frame_node.h" #include "core/components_ng/event/focus_hub.h" +#include "core/components_ng/manager/focus/focus_view.h" #include "core/components_ng/pattern/bubble//bubble_event_hub.h" #include "core/components_ng/pattern/bubble/bubble_layout_algorithm.h" #include "core/components_ng/pattern/bubble/bubble_layout_property.h" @@ -45,8 +46,9 @@ enum class DismissReason { TOUCH_OUTSIDE, CLOSE_BUTTON, }; -class BubblePattern : public PopupBasePattern { - DECLARE_ACE_TYPE(BubblePattern, PopupBasePattern); + +class BubblePattern : public PopupBasePattern, public FocusView { + DECLARE_ACE_TYPE(BubblePattern, PopupBasePattern, FocusView); public: BubblePattern() = default; @@ -110,6 +112,11 @@ public: return { FocusType::SCOPE, true }; } + std::list GetRouteOfFirstScope() override + { + return { 0, 0, 0 }; + } + void OnWindowHide() override; void OnWindowSizeChanged(int32_t width, int32_t height, WindowSizeChangeReason type) override; void StartEnteringAnimation(std::function finish); diff --git a/frameworks/core/components_ng/pattern/dialog/dialog_pattern.h b/frameworks/core/components_ng/pattern/dialog/dialog_pattern.h index 947e34c6b06..937d7b3d263 100644 --- a/frameworks/core/components_ng/pattern/dialog/dialog_pattern.h +++ b/frameworks/core/components_ng/pattern/dialog/dialog_pattern.h @@ -24,6 +24,7 @@ #include "base/memory/referenced.h" #include "core/components/dialog/dialog_properties.h" #include "core/components/dialog/dialog_theme.h" +#include "core/components_ng/manager/focus/focus_view.h" #include "core/components_ng/pattern/dialog//dialog_event_hub.h" #include "core/components_ng/pattern/dialog/dialog_accessibility_property.h" #include "core/components_ng/pattern/dialog/dialog_layout_algorithm.h" @@ -37,8 +38,8 @@ enum class DialogDismissReason { DIALOG_TOUCH_OUTSIDE, DIALOG_CLOSE_BUTTON, }; -class DialogPattern : public PopupBasePattern { - DECLARE_ACE_TYPE(DialogPattern, PopupBasePattern); +class DialogPattern : public PopupBasePattern, public FocusView { + DECLARE_ACE_TYPE(DialogPattern, PopupBasePattern, FocusView); public: DialogPattern(const RefPtr& dialogTheme, const RefPtr& customNode) @@ -96,6 +97,11 @@ public: return { FocusType::SCOPE, true }; } + std::list GetRouteOfFirstScope() override + { + return { 0, 0 }; + } + void BuildChild(const DialogProperties& dialogProperties); void ToJsonValue(std::unique_ptr& json) const override; diff --git a/frameworks/core/components_ng/pattern/menu/menu_item/menu_item_pattern.cpp b/frameworks/core/components_ng/pattern/menu/menu_item/menu_item_pattern.cpp index 0a9b888eb27..4cf92b30db2 100644 --- a/frameworks/core/components_ng/pattern/menu/menu_item/menu_item_pattern.cpp +++ b/frameworks/core/components_ng/pattern/menu/menu_item/menu_item_pattern.cpp @@ -262,11 +262,11 @@ void MenuItemPattern::ShowSubMenu() auto parentMenu = GetMenu(); CHECK_NULL_VOID(parentMenu); // parentMenu no need focus - auto focusMenu = GetMenu(true); - CHECK_NULL_VOID(focusMenu); - auto focusHub = focusMenu->GetFocusHub(); - CHECK_NULL_VOID(focusHub); - focusHub->SetParentFocusable(false); + auto menuNode = GetMenu(true); + CHECK_NULL_VOID(menuNode); + auto menuPattern = menuNode->GetPattern(); + CHECK_NULL_VOID(menuPattern); + menuPattern->FocusViewHide(); auto parentMenuPattern = parentMenu->GetPattern(); CHECK_NULL_VOID(parentMenuPattern); auto showedSubMenu = parentMenuPattern->GetShowedSubMenu(); @@ -285,10 +285,10 @@ void MenuItemPattern::ShowSubMenu() auto customNode = NG::ViewStackProcessor::GetInstance()->Finish(); bool isSelectOverlayMenu = IsSelectOverlayMenu(); MenuParam param; - auto layoutProps = focusMenu->GetLayoutProperty(); + auto layoutProps = menuNode->GetLayoutProperty(); CHECK_NULL_VOID(layoutProps); param.isShowInSubWindow = layoutProps->GetShowInSubWindowValue(false); - auto focusMenuRenderContext = focusMenu->GetRenderContext(); + auto focusMenuRenderContext = menuNode->GetRenderContext(); CHECK_NULL_VOID(focusMenuRenderContext); if (focusMenuRenderContext->GetBackBlurStyle().has_value()) { auto focusMenuBlurStyle = focusMenuRenderContext->GetBackBlurStyle(); @@ -322,9 +322,7 @@ void MenuItemPattern::ShowSubMenuHelper(const RefPtr& subMenu) RegisterWrapperMouseEvent(); // select overlay menu no need focus if (!isSelectOverlayMenu) { - auto focusHub = subMenu->GetOrCreateFocusHub(); - CHECK_NULL_VOID(focusHub); - focusHub->RequestFocusWithDefaultFocusFirstly(); + menuPattern->FocusViewShow(); } } diff --git a/frameworks/core/components_ng/pattern/menu/menu_pattern.h b/frameworks/core/components_ng/pattern/menu/menu_pattern.h index 511ffe23e2c..541be12b724 100644 --- a/frameworks/core/components_ng/pattern/menu/menu_pattern.h +++ b/frameworks/core/components_ng/pattern/menu/menu_pattern.h @@ -52,8 +52,8 @@ enum class MenuType { SELECT_OVERLAY_RIGHT_CLICK_MENU, // menu type used for select overlay menu triggered by right-click }; -class MenuPattern : public Pattern { - DECLARE_ACE_TYPE(MenuPattern, Pattern); +class MenuPattern : public Pattern, public FocusView { + DECLARE_ACE_TYPE(MenuPattern, Pattern, FocusView); public: MenuPattern(int32_t targetId, std::string tag, MenuType type) @@ -71,6 +71,16 @@ public: return { FocusType::SCOPE, true }; } + std::list GetRouteOfFirstScope() override + { + return { 0, 0 }; + } + + bool IsFocusViewLegal() override + { + return type_ == MenuType::MENU || type_ == MenuType::CONTEXT_MENU || type_ == MenuType::SUB_MENU; + } + RefPtr CreateLayoutProperty() override { return MakeRefPtr(); diff --git a/frameworks/core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.cpp b/frameworks/core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.cpp index c3efda190d4..aba2fa89097 100644 --- a/frameworks/core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.cpp +++ b/frameworks/core/components_ng/pattern/menu/wrapper/menu_wrapper_pattern.cpp @@ -109,10 +109,9 @@ void MenuWrapperPattern::HideSubMenu() // SelectOverlay's custom menu does not need to be focused. auto isCustomMenu = IsSelectOverlayCustomMenu(menuHub); if (!isCustomMenu) { - auto focusHub = menuHub->GetFocusHub(); - CHECK_NULL_VOID(focusHub); - focusHub->SetParentFocusable(true); - focusHub->RequestFocusImmediately(); + auto menuPattern = menuHub->GetPattern(); + CHECK_NULL_VOID(menuPattern); + menuPattern->FocusViewShow(); } } host->RemoveChild(subMenu); diff --git a/frameworks/core/components_ng/pattern/navigation/nav_bar_pattern.h b/frameworks/core/components_ng/pattern/navigation/nav_bar_pattern.h index 762e54dd040..2af69694443 100755 --- a/frameworks/core/components_ng/pattern/navigation/nav_bar_pattern.h +++ b/frameworks/core/components_ng/pattern/navigation/nav_bar_pattern.h @@ -28,8 +28,8 @@ namespace OHOS::Ace::NG { -class NavBarPattern : public Pattern { - DECLARE_ACE_TYPE(NavBarPattern, Pattern); +class NavBarPattern : public Pattern, public FocusView { + DECLARE_ACE_TYPE(NavBarPattern, Pattern, FocusView); public: NavBarPattern() = default; @@ -129,6 +129,20 @@ public: return { FocusType::SCOPE, true }; } + std::list GetRouteOfFirstScope() override + { + return { 2, 0 }; + } + + std::string GetEntryFocusViewName() override + { + /* + |-> Navigation (root focus view) + |-> NavBar + */ + return V2::NAVIGATION_VIEW_ETS_TAG; + } + int32_t GetMaxMenuNum() const { return maxMenuNums_; diff --git a/frameworks/core/components_ng/pattern/navigation/navigation_pattern.cpp b/frameworks/core/components_ng/pattern/navigation/navigation_pattern.cpp index 460065995b4..c8a16f060b3 100644 --- a/frameworks/core/components_ng/pattern/navigation/navigation_pattern.cpp +++ b/frameworks/core/components_ng/pattern/navigation/navigation_pattern.cpp @@ -368,16 +368,9 @@ void NavigationPattern::CheckTopNavPathChange( CHECK_NULL_VOID(eventHub); NotifyPageHide(preTopNavPath->first); } - auto focusHub = preTopNavDestination->GetOrCreateFocusHub(); - focusHub->SetParentFocusable(false); - focusHub->LostFocus(); } } else { // navBar to new top page case - auto navBarNode = AceType::DynamicCast(hostNode->GetNavBarNode()); - CHECK_NULL_VOID(navBarNode); - auto focusHub = navBarNode->GetOrCreateFocusHub(); - focusHub->LostFocus(); } RefPtr newTopNavDestination; // fire onShown and requestFocus Event @@ -391,11 +384,10 @@ void NavigationPattern::CheckTopNavPathChange( if (!navDestinationPattern->GetIsOnShow()) { NotifyPageShow(newTopNavPath->first); } - auto focusHub = newTopNavDestination->GetOrCreateFocusHub(); - context->AddAfterLayoutTask([focusHub]() { - focusHub->SetParentFocusable(true); - focusHub->RequestFocus(); - }); + auto navDestinationFocusView = AceType::DynamicCast(navDestinationPattern); + CHECK_NULL_VOID(navDestinationFocusView); + navDestinationFocusView->SetIsViewRootScopeFocused(false); + navDestinationFocusView->FocusViewShow(); } } else { // back to navBar case @@ -418,8 +410,10 @@ void NavigationPattern::CheckTopNavPathChange( } } navBarNode->GetEventHub()->SetEnabledInternal(true); - auto focusHub = navBarNode->GetOrCreateFocusHub(); - focusHub->RequestFocus(); + auto navBarFocusView = navBarNode->GetPattern(); + CHECK_NULL_VOID(navBarFocusView); + navBarFocusView->SetIsViewRootScopeFocused(false); + navBarFocusView->FocusViewShow(); } bool isShow = false; bool isDialog = @@ -851,16 +845,21 @@ bool NavigationPattern::OnDirtyLayoutWrapperSwap(const RefPtr& di navBarLayoutProperty->UpdateVisibility(VisibleType::VISIBLE); navBarNode->SetJSViewActive(true); } - if (navDestinationNode->GetChildren().size() <= EMPTY_DESTINATION_CHILD_SIZE && + auto navDestinationFocusHub = navDestinationNode->GetFocusHub(); + CHECK_NULL_VOID(navDestinationFocusHub); + auto defaultFocusHub = navDestinationFocusHub->GetChildFocusNodeByType(FocusNodeType::DEFAULT); + if (!defaultFocusHub && navDestinationNode->GetChildren().size() <= EMPTY_DESTINATION_CHILD_SIZE && navDestinationPattern->GetBackButtonState()) { - auto focusHub = navDestinationNode->GetOrCreateFocusHub(); - focusHub->SetFocusable(true); - focusHub->SetParentFocusable(true); auto titleBarNode = AceType::DynamicCast(navDestinationNode->GetTitleBarNode()); - CHECK_NULL_VOID(titleBarNode); - auto backButtonNode = AceType::DynamicCast(titleBarNode->GetBackButton()); - backButtonNode->GetOrCreateFocusHub()->SetIsDefaultFocus(true); - focusHub->RequestFocusWithDefaultFocusFirstly(); + if (titleBarNode) { + auto backButtonNode = AceType::DynamicCast(titleBarNode->GetBackButton()); + backButtonNode->GetOrCreateFocusHub()->SetIsDefaultFocus(true); + } + } + auto navDestinationFocusView = navDestinationNode->GetPattern(); + if (navDestinationFocusView) { + navDestinationFocusView->SetIsViewRootScopeFocused(false); + navDestinationFocusView->FocusViewShow(); } }, TaskExecutor::TaskType::UI); diff --git a/frameworks/core/components_ng/pattern/navigation/navigation_pattern.h b/frameworks/core/components_ng/pattern/navigation/navigation_pattern.h index 5edd2bcf7b8..cfbf37b3da8 100644 --- a/frameworks/core/components_ng/pattern/navigation/navigation_pattern.h +++ b/frameworks/core/components_ng/pattern/navigation/navigation_pattern.h @@ -36,8 +36,8 @@ namespace OHOS::Ace::NG { using namespace Framework; using OnNavigationAnimation = std::function; -class NavigationPattern : public Pattern { - DECLARE_ACE_TYPE(NavigationPattern, Pattern); +class NavigationPattern : public Pattern, public FocusView { + DECLARE_ACE_TYPE(NavigationPattern, Pattern, FocusView); public: NavigationPattern(); @@ -82,6 +82,11 @@ public: return { false, true, ScopeType::FLEX }; } + std::list GetRouteOfFirstScope() override + { + return {}; + } + void SetNavDestination(std::function&& builder) { builder_ = std::move(builder); diff --git a/frameworks/core/components_ng/pattern/navrouter/navdestination_pattern.h b/frameworks/core/components_ng/pattern/navrouter/navdestination_pattern.h index 5b20c2b117a..ca86b1c18be 100644 --- a/frameworks/core/components_ng/pattern/navrouter/navdestination_pattern.h +++ b/frameworks/core/components_ng/pattern/navrouter/navdestination_pattern.h @@ -28,11 +28,12 @@ #include "core/components_ng/pattern/navrouter/navdestination_layout_property.h" #include "core/components_ng/pattern/pattern.h" #include "core/components_ng/syntax/shallow_builder.h" +#include "core/components_v2/inspector/inspector_constants.h" namespace OHOS::Ace::NG { -class NavDestinationPattern : public Pattern { - DECLARE_ACE_TYPE(NavDestinationPattern, Pattern); +class NavDestinationPattern : public Pattern, public FocusView { + DECLARE_ACE_TYPE(NavDestinationPattern, Pattern, FocusView); public: explicit NavDestinationPattern(const RefPtr& shallowBuilder) : shallowBuilder_(shallowBuilder) {} @@ -129,6 +130,20 @@ public: return { FocusType::SCOPE, true }; } + std::list GetRouteOfFirstScope() override + { + return { 2, 0 }; + } + + std::string GetEntryFocusViewName() override + { + /* + |-> Navigation (root focus view) + |-> NavDestination + */ + return V2::NAVIGATION_VIEW_ETS_TAG; + } + void SetIsOnShow(bool isOnShow) { isOnShow_ = isOnShow; diff --git a/frameworks/core/components_ng/pattern/overlay/modal_presentation_pattern.h b/frameworks/core/components_ng/pattern/overlay/modal_presentation_pattern.h index eded11c9d39..41cc45b8203 100644 --- a/frameworks/core/components_ng/pattern/overlay/modal_presentation_pattern.h +++ b/frameworks/core/components_ng/pattern/overlay/modal_presentation_pattern.h @@ -19,13 +19,14 @@ #include "base/memory/ace_type.h" #include "base/memory/referenced.h" #include "core/common/ace_application_info.h" +#include "core/components_ng/manager/focus/focus_view.h" #include "core/components_ng/pattern/overlay/modal_presentation_layout_algorithm.h" #include "core/components_ng/pattern/overlay/modal_style.h" #include "core/components_ng/pattern/overlay/popup_base_pattern.h" namespace OHOS::Ace::NG { -class ACE_EXPORT ModalPresentationPattern : public PopupBasePattern { - DECLARE_ACE_TYPE(ModalPresentationPattern, PopupBasePattern); +class ACE_EXPORT ModalPresentationPattern : public PopupBasePattern, public FocusView { + DECLARE_ACE_TYPE(ModalPresentationPattern, PopupBasePattern, FocusView); public: ModalPresentationPattern(int32_t targetId, ModalTransition type, std::function&& callback) @@ -106,6 +107,11 @@ public: return { FocusType::SCOPE, true }; } + std::list GetRouteOfFirstScope() override + { + return { 0 }; + } + bool IsExecuteOnDisappear() const { return isExecuteOnDisappear_; diff --git a/frameworks/core/components_ng/pattern/overlay/overlay_manager.cpp b/frameworks/core/components_ng/pattern/overlay/overlay_manager.cpp index f68ebdfe870..ff705122bb5 100644 --- a/frameworks/core/components_ng/pattern/overlay/overlay_manager.cpp +++ b/frameworks/core/components_ng/pattern/overlay/overlay_manager.cpp @@ -1716,7 +1716,8 @@ void OverlayManager::CloseDialog(const RefPtr& dialogNode) TAG_LOGD(AceLogTag::ACE_OVERLAY, "close dialog enter"); DeleteDialogHotAreas(dialogNode); auto dialogLayoutProp = AceType::DynamicCast(dialogNode->GetLayoutProperty()); - if (dialogLayoutProp->GetShowInSubWindowValue(false) && dialogLayoutProp->GetIsModal().value_or(true)) { + if (dialogLayoutProp && dialogLayoutProp->GetShowInSubWindowValue(false) && + dialogLayoutProp->GetIsModal().value_or(true)) { auto parentPipelineContext = PipelineContext::GetMainPipelineContext(); CHECK_NULL_VOID(parentPipelineContext); auto parentOverlayManager = parentPipelineContext->GetOverlayManager(); @@ -2170,117 +2171,18 @@ bool OverlayManager::RemoveOverlayInSubwindow() void OverlayManager::FocusOverlayNode(const RefPtr& overlayNode, bool isInSubWindow) { CHECK_NULL_VOID(overlayNode); - auto focusHub = overlayNode->GetOrCreateFocusHub(); - CHECK_NULL_VOID(focusHub); - focusHub->SetParentFocusable(true); - focusHub->RequestFocusWithDefaultFocusFirstly(); + auto overlayHub = overlayNode->GetFocusHub(); + CHECK_NULL_VOID(overlayHub); + auto focusView = overlayHub->GetFirstChildFocusView(); + CHECK_NULL_VOID(focusView); + focusView->FocusViewShow(); } -void OverlayManager::BlurOverlayNode(const RefPtr& currentOverlay, bool isInSubWindow) -{ - auto currentFocusHub = currentOverlay->GetOrCreateFocusHub(); - CHECK_NULL_VOID(currentFocusHub); - currentFocusHub->SetParentFocusable(false); - currentFocusHub->LostFocus(); +void OverlayManager::BlurOverlayNode(const RefPtr& currentOverlay, bool isInSubWindow) {} - auto rootNode = rootNodeWeak_.Upgrade(); - CHECK_NULL_VOID(rootNode); - if (rootNode->GetChildren().size() > 1) { - auto collection = rootNode->GetChildren(); - for (auto iter = collection.rbegin(); iter != collection.rend(); ++iter) { - auto overlay = DynamicCast(*iter); - CHECK_NULL_VOID(overlay); - auto pattern = overlay->GetPattern(); - if (currentOverlay != overlay && - (InstanceOf(pattern) || InstanceOf(pattern) || - InstanceOf(pattern) || InstanceOf(pattern)) && - overlay->GetTag() != V2::SELECT_OVERLAY_ETS_TAG && - !overlay->IsRemoving()) { - // Focus returns to the previous in the overlay - FocusOverlayNode(overlay, isInSubWindow); - return; - } - } - } - if (isInSubWindow) { - // no need to set page request focus in sub window. - return; - } +void OverlayManager::BlurLowerNode(const RefPtr& currentOverlay) {} - auto pageNode = GetLastPage(); - CHECK_NULL_VOID(pageNode); - auto pageFocusHub = pageNode->GetFocusHub(); - CHECK_NULL_VOID(pageFocusHub); - pageFocusHub->SetParentFocusable(true); - pageFocusHub->RequestFocus(); -} - -void OverlayManager::BlurLowerNode(const RefPtr& currentOverlay) -{ - auto root = DynamicCast(currentOverlay->GetParent()); - CHECK_NULL_VOID(root); - auto children = root->GetChildren(); - for (auto iter = children.rbegin(); iter != children.rend(); ++iter) { - auto node = DynamicCast(*iter); - CHECK_NULL_VOID(node); - if (currentOverlay == node) { - continue; - } - if (node->GetTag() == V2::STAGE_ETS_TAG) { - auto pageNode = GetLastPage(); - CHECK_NULL_VOID(pageNode); - auto pageFocusHub = pageNode->GetFocusHub(); - CHECK_NULL_VOID(pageFocusHub); - pageFocusHub->SetParentFocusable(false); - pageFocusHub->LostFocus(); - return; - } - auto focusHub = node->GetOrCreateFocusHub(); - if (focusHub->IsCurrentFocus()) { - focusHub->SetParentFocusable(false); - focusHub->LostFocus(); - return; - } - } -} - -void OverlayManager::ResetLowerNodeFocusable(const RefPtr& currentOverlay) -{ - CHECK_NULL_VOID(currentOverlay); - auto root = DynamicCast(currentOverlay->GetParent()); - CHECK_NULL_VOID(root); - auto children = root->GetChildren(); - for (auto iter = children.rbegin(); iter != children.rend(); ++iter) { - auto node = DynamicCast(*iter); - CHECK_NULL_VOID(node); - if (currentOverlay == node) { - continue; - } - if (node->GetTag() == V2::STAGE_ETS_TAG) { - auto parent = node->GetParent(); - if (parent && parent->GetTag() != V2::PAGE_ETS_TAG) { - return; - } - auto pageNode = GetLastPage(); - CHECK_NULL_VOID(pageNode); - auto pageFocusHub = pageNode->GetFocusHub(); - CHECK_NULL_VOID(pageFocusHub); - pageFocusHub->SetParentFocusable(true); - return; - } - if (node->GetTag() == V2::ATOMIC_SERVICE_ETS_TAG || node->GetTag() == V2::SHEET_WRAPPER_TAG) { - auto currentFocusHub = node->GetFocusHub(); - CHECK_NULL_VOID(currentFocusHub); - currentFocusHub->SetParentFocusable(true); - return; - } - auto focusHub = node->GetOrCreateFocusHub(); - if (focusHub->IsCurrentFocus()) { - focusHub->SetParentFocusable(true); - return; - } - } -} +void OverlayManager::ResetLowerNodeFocusable(const RefPtr& currentOverlay) {} void OverlayManager::SaveLastModalNode() { @@ -2474,50 +2376,16 @@ void OverlayManager::BindContentCover(bool isShow, std::functionGetStageManager()->GetLastPage(); - CHECK_NULL_VOID(pageNode); - auto pageFocusHub = pageNode->GetFocusHub(); - CHECK_NULL_VOID(pageFocusHub); - pageFocusHub->SetParentFocusable(false); - pageFocusHub->LostFocus(); - for (auto modal = modalList_.begin(); modal != modalList_.end(); modal++) { - auto modalNode = (*modal).Upgrade(); - CHECK_NULL_VOID(modalNode); - auto modalFocusHub = modalNode->GetFocusHub(); - CHECK_NULL_VOID(modalFocusHub); - modalFocusHub->SetParentFocusable(false); - modalFocusHub->LostFocus(); - } - if (modalList_.empty()) { - return; - } auto topModalNode = modalList_.back().Upgrade(); CHECK_NULL_VOID(topModalNode); - auto topModalFocusHub = topModalNode->GetFocusHub(); - CHECK_NULL_VOID(topModalFocusHub); - topModalFocusHub->SetParentFocusable(true); - topModalFocusHub->RequestFocusWithDefaultFocusFirstly(); + auto topModalFocusView = topModalNode->GetPattern(); + CHECK_NULL_VOID(topModalFocusView); + topModalFocusView->FocusViewShow(); } -void OverlayManager::ModalPageLostFocus(const RefPtr& node) -{ - auto modalFocusHub = node->GetFocusHub(); - CHECK_NULL_VOID(modalFocusHub); - modalFocusHub->SetParentFocusable(false); - modalFocusHub->LostFocus(); -} +void OverlayManager::ModalPageLostFocus(const RefPtr& node) {} -void OverlayManager::FireModalPageHide() -{ - auto lastModalNode = lastModalNode_.Upgrade(); - CHECK_NULL_VOID(lastModalNode); - auto lastModalFocusHub = lastModalNode->GetFocusHub(); - CHECK_NULL_VOID(lastModalFocusHub); - lastModalFocusHub->SetParentFocusable(true); - lastModalFocusHub->RequestFocus(); -} +void OverlayManager::FireModalPageHide() {} void OverlayManager::PlayDefaultModalTransition(const RefPtr& modalNode, bool isTransitionIn) { @@ -3881,16 +3749,5 @@ float OverlayManager::GetRootHeight() const return rootHeight; } -void OverlayManager::CheckReturnFocus(RefPtr node) -{ - auto focusHub = node->GetFocusHub(); - CHECK_NULL_VOID(focusHub); - if (focusHub->IsCurrentFocus()) { - auto pageNode = GetLastPage(); - CHECK_NULL_VOID(pageNode); - auto pageFocusHub = pageNode->GetFocusHub(); - CHECK_NULL_VOID(pageFocusHub); - pageFocusHub->RequestFocusWithDefaultFocusFirstly(); - } -} +void OverlayManager::CheckReturnFocus(RefPtr node) {} } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/overlay/sheet_presentation_pattern.h b/frameworks/core/components_ng/pattern/overlay/sheet_presentation_pattern.h index bdfe462b55a..5104510b321 100644 --- a/frameworks/core/components_ng/pattern/overlay/sheet_presentation_pattern.h +++ b/frameworks/core/components_ng/pattern/overlay/sheet_presentation_pattern.h @@ -22,6 +22,7 @@ #include "base/memory/ace_type.h" #include "base/memory/referenced.h" #include "core/components/common/properties/alignment.h" +#include "core/components_ng/manager/focus/focus_view.h" #include "core/components_ng/pattern/linear_layout/linear_layout_algorithm.h" #include "core/components_ng/pattern/linear_layout/linear_layout_pattern.h" #include "core/components_ng/pattern/linear_layout/linear_layout_property.h" @@ -32,8 +33,8 @@ #include "core/pipeline_ng/pipeline_context.h" namespace OHOS::Ace::NG { -class ACE_EXPORT SheetPresentationPattern : public LinearLayoutPattern, public PopupBasePattern { - DECLARE_ACE_TYPE(SheetPresentationPattern, LinearLayoutPattern, PopupBasePattern); +class ACE_EXPORT SheetPresentationPattern : public LinearLayoutPattern, public PopupBasePattern, public FocusView { + DECLARE_ACE_TYPE(SheetPresentationPattern, LinearLayoutPattern, PopupBasePattern, FocusView); public: SheetPresentationPattern( @@ -206,6 +207,11 @@ public: return { FocusType::SCOPE, true }; } + std::list GetRouteOfFirstScope() override + { + return { 1, 0 }; + } + bool IsExecuteOnDisappear() const { return isExecuteOnDisappear_; diff --git a/frameworks/core/components_ng/pattern/stage/page_pattern.h b/frameworks/core/components_ng/pattern/stage/page_pattern.h index 8b2f347dd5a..956a77f66e5 100644 --- a/frameworks/core/components_ng/pattern/stage/page_pattern.h +++ b/frameworks/core/components_ng/pattern/stage/page_pattern.h @@ -44,8 +44,8 @@ enum class RouterPageState { }; // PagePattern is the base class for page root render node. -class ACE_EXPORT PagePattern : public ContentRootPattern { - DECLARE_ACE_TYPE(PagePattern, ContentRootPattern); +class ACE_EXPORT PagePattern : public ContentRootPattern, public FocusView { + DECLARE_ACE_TYPE(PagePattern, ContentRootPattern, FocusView); public: explicit PagePattern(const RefPtr& pageInfo) : pageInfo_(pageInfo) {} @@ -123,6 +123,11 @@ public: return { FocusType::SCOPE, true }; } + std::list GetRouteOfFirstScope() override + { + return { 0 }; + } + const SharedTransitionMap& GetSharedTransitionMap() const { return sharedTransitionMap_; diff --git a/frameworks/core/components_ng/pattern/stage/stage_manager.cpp b/frameworks/core/components_ng/pattern/stage/stage_manager.cpp index f5274139280..242ebea4ed1 100644 --- a/frameworks/core/components_ng/pattern/stage/stage_manager.cpp +++ b/frameworks/core/components_ng/pattern/stage/stage_manager.cpp @@ -58,10 +58,9 @@ void FirePageTransition(const RefPtr& page, PageTransitionType transi CHECK_NULL_VOID(context); auto page = weak.Upgrade(); CHECK_NULL_VOID(page); - auto pageFocusHub = page->GetFocusHub(); - CHECK_NULL_VOID(pageFocusHub); - pageFocusHub->SetParentFocusable(false); - pageFocusHub->LostFocus(); + auto pattern = page->GetPattern(); + CHECK_NULL_VOID(pattern); + pattern->FocusViewHide(); if (transitionType == PageTransitionType::EXIT_POP && page->GetParent()) { auto stageNode = page->GetParent(); stageNode->RemoveChild(page); @@ -70,8 +69,6 @@ void FirePageTransition(const RefPtr& page, PageTransitionType transi return; } page->GetEventHub()->SetEnabled(true); - auto pattern = page->GetPattern(); - CHECK_NULL_VOID(pattern); pattern->SetPageInTransition(false); pattern->ProcessHideState(); context->MarkNeedFlushMouseEvent(); @@ -90,10 +87,7 @@ void FirePageTransition(const RefPtr& page, PageTransitionType transi CHECK_NULL_VOID(pattern); pattern->SetPageInTransition(false); - auto pageFocusHub = page->GetFocusHub(); - CHECK_NULL_VOID(pageFocusHub); - pageFocusHub->SetParentFocusable(true); - pageFocusHub->RequestFocusWithDefaultFocusFirstly(); + pattern->FocusViewShow(); auto context = PipelineContext::GetCurrentContext(); CHECK_NULL_VOID(context); context->MarkNeedFlushMouseEvent(); @@ -403,6 +397,7 @@ void StageManager::FirePageHide(const RefPtr& node, PageTransitionType t CHECK_NULL_VOID(pageNode); auto pagePattern = pageNode->GetPattern(); CHECK_NULL_VOID(pagePattern); + pagePattern->FocusViewHide(); pagePattern->OnHide(); if (transitionType == PageTransitionType::NONE) { // If there is a page transition, this function should execute after page transition, @@ -410,11 +405,6 @@ void StageManager::FirePageHide(const RefPtr& node, PageTransitionType t pagePattern->ProcessHideState(); } - auto pageFocusHub = pageNode->GetFocusHub(); - CHECK_NULL_VOID(pageFocusHub); - pageFocusHub->SetParentFocusable(false); - pageFocusHub->LostFocus(); - auto context = PipelineContext::GetCurrentContext(); CHECK_NULL_VOID(context); context->MarkNeedFlushMouseEvent(); @@ -425,13 +415,10 @@ void StageManager::FirePageShow(const RefPtr& node, PageTransitionType t auto pageNode = DynamicCast(node); CHECK_NULL_VOID(pageNode); auto layoutProperty = pageNode->GetLayoutProperty(); - auto pageFocusHub = pageNode->GetFocusHub(); - CHECK_NULL_VOID(pageFocusHub); - pageFocusHub->SetParentFocusable(true); - pageFocusHub->RequestFocusWithDefaultFocusFirstly(); auto pagePattern = pageNode->GetPattern(); CHECK_NULL_VOID(pagePattern); + pagePattern->FocusViewShow(); pagePattern->OnShow(); // With or without a page transition, we need to make the coming page visible first pagePattern->ProcessShowState(); diff --git a/frameworks/core/components_ng/pattern/window_scene/scene/system_window_scene.cpp b/frameworks/core/components_ng/pattern/window_scene/scene/system_window_scene.cpp index cbcddfd6826..3b8f402dd3c 100644 --- a/frameworks/core/components_ng/pattern/window_scene/scene/system_window_scene.cpp +++ b/frameworks/core/components_ng/pattern/window_scene/scene/system_window_scene.cpp @@ -186,35 +186,32 @@ void SystemWindowScene::RegisterFocusCallback() ContainerScope scope(instanceId); auto pipelineContext = PipelineContext::GetCurrentContext(); CHECK_NULL_VOID(pipelineContext); + auto pattern = weakThis.Upgrade(); + auto frameNode = pattern ? pattern->GetHost() : nullptr; + pipelineContext->SetFocusedWindowSceneNode(frameNode); pipelineContext->PostAsyncEvent([weakThis]() { auto self = weakThis.Upgrade(); CHECK_NULL_VOID(self); - auto host = self->GetHost(); - CHECK_NULL_VOID(host); - auto focusHub = host->GetFocusHub(); - CHECK_NULL_VOID(focusHub); - focusHub->SetParentFocusable(true); - focusHub->RequestFocusWithDefaultFocusFirstly(); + self->FocusViewShow(); }, TaskExecutor::TaskType::UI); }; session_->SetNotifyUIRequestFocusFunc(requestFocusCallback); - auto lostFocusCallback = [weakThis = WeakClaim(this), instanceId = instanceId_]() { - ContainerScope scope(instanceId); - auto pipelineContext = PipelineContext::GetCurrentContext(); - CHECK_NULL_VOID(pipelineContext); - pipelineContext->PostAsyncEvent([weakThis]() { - auto self = weakThis.Upgrade(); - CHECK_NULL_VOID(self); - auto host = self->GetHost(); - CHECK_NULL_VOID(host); - auto focusHub = host->GetFocusHub(); - CHECK_NULL_VOID(focusHub); - focusHub->SetParentFocusable(false); - }, - TaskExecutor::TaskType::UI); - }; + auto lostFocusCallback = [weakThis = WeakClaim(this), instanceId = instanceId_]() {}; session_->SetNotifyUILostFocusFunc(lostFocusCallback); } + +void SystemWindowScene::LostViewFocus() +{ + TAG_LOGI( + AceLogTag::ACE_FOCUS, "Focus view: %{public}s/%{public}d lost focus", GetFrameName().c_str(), GetFrameId()); + auto pipeline = PipelineContext::GetCurrentContext(); + CHECK_NULL_VOID(pipeline); + auto screenNode = pipeline->GetScreenNode(); + CHECK_NULL_VOID(screenNode); + auto screenNodeFocusHub = screenNode->GetFocusHub(); + CHECK_NULL_VOID(screenNodeFocusHub); + screenNodeFocusHub->LostFocus(BlurReason::VIEW_SWITCH); +} } // namespace OHOS::Ace::NG diff --git a/frameworks/core/components_ng/pattern/window_scene/scene/system_window_scene.h b/frameworks/core/components_ng/pattern/window_scene/scene/system_window_scene.h index 4c9b103969e..3a29523fad5 100644 --- a/frameworks/core/components_ng/pattern/window_scene/scene/system_window_scene.h +++ b/frameworks/core/components_ng/pattern/window_scene/scene/system_window_scene.h @@ -20,11 +20,12 @@ #include "session/host/include/session.h" #include "core/common/container.h" +#include "core/components_ng/manager/focus/focus_view.h" #include "core/components_ng/pattern/stack/stack_pattern.h" namespace OHOS::Ace::NG { -class SystemWindowScene : public StackPattern { - DECLARE_ACE_TYPE(SystemWindowScene, StackPattern); +class SystemWindowScene : public StackPattern, public FocusView { + DECLARE_ACE_TYPE(SystemWindowScene, StackPattern, FocusView); public: explicit SystemWindowScene(const sptr& session); @@ -43,6 +44,13 @@ public: visible ? "true" : "false"); } + std::list GetRouteOfFirstScope() override + { + return { 0 }; + } + + void LostViewFocus() override; + private: void OnAttachToFrameNode() override; void OnBoundsChanged(const Rosen::Vector4f& bounds); diff --git a/frameworks/core/components_ng/pattern/window_scene/scene/window_scene.cpp b/frameworks/core/components_ng/pattern/window_scene/scene/window_scene.cpp index e066547bcca..ad8a6ffb7cd 100644 --- a/frameworks/core/components_ng/pattern/window_scene/scene/window_scene.cpp +++ b/frameworks/core/components_ng/pattern/window_scene/scene/window_scene.cpp @@ -156,7 +156,6 @@ void WindowScene::RegisterFocusCallback() auto focusHub = host->GetFocusHub(); CHECK_NULL_VOID(focusHub); focusHub->SetParentFocusable(true); - focusHub->RequestFocusWithDefaultFocusFirstly(); }, TaskExecutor::TaskType::UI); }; diff --git a/frameworks/core/event/key_event.h b/frameworks/core/event/key_event.h index c65d0f0941e..95cdfdcb589 100644 --- a/frameworks/core/event/key_event.h +++ b/frameworks/core/event/key_event.h @@ -647,6 +647,7 @@ enum class BlurReason : int32_t { FOCUS_SWITCH = 0, WINDOW_BLUR = 1, FRAME_DESTROY = 2, + VIEW_SWITCH = 3, }; using OnKeyEventFunc = std::function; diff --git a/frameworks/core/pipeline_ng/pipeline_context.cpp b/frameworks/core/pipeline_ng/pipeline_context.cpp index eac26b17540..7de466f2925 100755 --- a/frameworks/core/pipeline_ng/pipeline_context.cpp +++ b/frameworks/core/pipeline_ng/pipeline_context.cpp @@ -628,6 +628,7 @@ void PipelineContext::FlushVsync(uint64_t nanoTimestamp, uint32_t frameCount) FlushMessages(); InspectDrew(); if (!isFormRender_ && onShow_ && onFocus_) { + FlushFocusView(); FlushFocus(); } // Close input method in the SCB window. @@ -741,18 +742,6 @@ void PipelineContext::FlushFocus() ACE_FUNCTION_TRACK(); ACE_FUNCTION_TRACE(); - auto defaultFocusNode = dirtyDefaultFocusNode_.Upgrade(); - if (!defaultFocusNode) { - dirtyDefaultFocusNode_.Reset(); - } else { - auto focusNodeHub = defaultFocusNode->GetFocusHub(); - if (focusNodeHub) { - RequestDefaultFocus(focusNodeHub); - } - dirtyFocusNode_.Reset(); - dirtyFocusScope_.Reset(); - dirtyDefaultFocusNode_.Reset(); - } auto requestFocusNode = dirtyRequestFocusNode_.Upgrade(); if (!requestFocusNode) { dirtyRequestFocusNode_.Reset(); @@ -764,7 +753,6 @@ void PipelineContext::FlushFocus() } dirtyFocusNode_.Reset(); dirtyFocusScope_.Reset(); - dirtyDefaultFocusNode_.Reset(); dirtyRequestFocusNode_.Reset(); return; } @@ -780,7 +768,6 @@ void PipelineContext::FlushFocus() } dirtyFocusNode_.Reset(); dirtyFocusScope_.Reset(); - dirtyDefaultFocusNode_.Reset(); dirtyRequestFocusNode_.Reset(); return; } @@ -795,16 +782,21 @@ void PipelineContext::FlushFocus() } dirtyFocusNode_.Reset(); dirtyFocusScope_.Reset(); - dirtyDefaultFocusNode_.Reset(); dirtyRequestFocusNode_.Reset(); return; } - auto rootFocusHub = rootNode_ ? rootNode_->GetFocusHub() : nullptr; - if (rootFocusHub && !rootFocusHub->IsCurrentFocus()) { - auto curMainView = FocusHub::GetCurrentMainView(); - if (curMainView && curMainView->GetIsViewHasFocused()) { - rootFocusHub->RequestFocusImmediately(); - } +} + +void PipelineContext::FlushFocusView() +{ + CHECK_NULL_VOID(focusManager_); + auto lastFocusView = (focusManager_->GetLastFocusView()).Upgrade(); + CHECK_NULL_VOID(lastFocusView); + auto lastFocusViewHub = lastFocusView->GetFocusHub(); + CHECK_NULL_VOID(lastFocusViewHub); + if (lastFocusView && (!lastFocusViewHub->IsCurrentFocus() || !lastFocusView->GetIsViewHasFocused()) && + lastFocusViewHub->IsFocusableNode()) { + lastFocusView->RequestDefaultFocus(); } } @@ -953,6 +945,7 @@ void PipelineContext::SetupRootElement() selectOverlayManager_ = MakeRefPtr(rootNode_); postEventManager_ = MakeRefPtr(); dragDropManager_ = MakeRefPtr(); + focusManager_ = MakeRefPtr(); sharedTransitionManager_ = MakeRefPtr( DynamicCast(installationFree_ ? stageNode->GetParent()->GetParent() : stageNode->GetParent())); @@ -1010,6 +1003,7 @@ void PipelineContext::SetupSubRootElement() fullScreenManager_ = MakeRefPtr(rootNode_); selectOverlayManager_ = MakeRefPtr(rootNode_); dragDropManager_ = MakeRefPtr(); + focusManager_ = MakeRefPtr(); postEventManager_ = MakeRefPtr(); } @@ -2048,6 +2042,16 @@ bool PipelineContext::OnDumpInfo(const std::vector& params) const if (rootNode_->GetFocusHub()) { rootNode_->GetFocusHub()->DumpFocusTree(0); } + } else if (params[0] == "-focuswindowscene") { + auto windowSceneNode = GetFocusedWindowSceneNode(); + auto windowSceneFocusHub = windowSceneNode ? windowSceneNode->GetFocusHub() : nullptr; + if (windowSceneFocusHub) { + windowSceneFocusHub->DumpFocusTree(0); + } + } else if (params[0] == "-focusmanager") { + if (focusManager_) { + focusManager_->DumpFocusManager(); + } } else if (params[0] == "-accessibility" || params[0] == "-inspector") { auto accessibilityManager = GetAccessibilityManager(); if (accessibilityManager) { @@ -2305,13 +2309,13 @@ bool PipelineContext::OnKeyEvent(const KeyEvent& event) } auto isKeyTabDown = event.action == KeyAction::DOWN && event.IsKey({ KeyCode::KEY_TAB }); - auto curMainView = FocusHub::GetCurrentMainView(); - auto isViewRootScopeFocused = curMainView ? curMainView->GetIsViewRootScopeFocused() : true; + auto curFocusView = focusManager_ ? focusManager_->GetLastFocusView().Upgrade() : nullptr; + auto isViewRootScopeFocused = curFocusView ? curFocusView->GetIsViewRootScopeFocused() : true; isTabJustTriggerOnKeyEvent_ = false; - if (isKeyTabDown && isViewRootScopeFocused && curMainView) { + if (isKeyTabDown && isViewRootScopeFocused && curFocusView) { // Current focused on the view root scope. Tab key used to extend focus. // If return true. This tab key will just trigger onKeyEvent process. - isTabJustTriggerOnKeyEvent_ = curMainView->HandleFocusOnMainView(); + isTabJustTriggerOnKeyEvent_ = curFocusView->TriggerFocusMove(); } // Tab key set focus state from inactive to active. @@ -2319,9 +2323,10 @@ bool PipelineContext::OnKeyEvent(const KeyEvent& event) bool isHandleFocusActive = isKeyTabDown && SetIsFocusActive(true); isTabJustTriggerOnKeyEvent_ = isTabJustTriggerOnKeyEvent_ || isHandleFocusActive; - auto curMainViewFrameNode = curMainView ? curMainView->GetFrameNode() : nullptr; - if (!eventManager_->DispatchTabIndexEventNG(event, curMainViewFrameNode)) { - auto result = eventManager_->DispatchKeyEventNG(event, rootNode_); + auto curEntryFocusView = curFocusView ? curFocusView->GetEntryFocusView() : nullptr; + auto curEntryFocusViewFrame = curEntryFocusView ? curEntryFocusView->GetFrameNode() : nullptr; + if (!eventManager_->DispatchTabIndexEventNG(event, curEntryFocusViewFrame)) { + auto result = eventManager_->DispatchKeyEventNG(event, curEntryFocusViewFrame); if (!result && event.code == KeyCode::KEY_ESCAPE && event.action == KeyAction::DOWN) { CHECK_NULL_RETURN(overlayManager_, false); auto currentContainer = Container::Current(); @@ -2337,38 +2342,6 @@ bool PipelineContext::OnKeyEvent(const KeyEvent& event) return true; } -bool PipelineContext::RequestDefaultFocus(const RefPtr& mainView) -{ - if (!mainView || mainView->GetFocusType() != FocusType::SCOPE) { - return false; - } - mainView->SetIsViewHasFocused(true); - auto viewRootScope = mainView->GetMainViewRootScope(); - auto defaultFocusNode = mainView->GetChildFocusNodeByType(FocusNodeType::DEFAULT); - if (!mainView->IsDefaultHasFocused() && defaultFocusNode && defaultFocusNode->IsFocusableWholePath()) { - mainView->SetIsViewRootScopeFocused(viewRootScope, false); - auto ret = defaultFocusNode->RequestFocusImmediately(); - mainView->SetIsDefaultHasFocused(true); - TAG_LOGI(AceLogTag::ACE_FOCUS, - "Target view's default focus is %{public}s/%{public}d. Request default focus return: %{public}d.", - defaultFocusNode->GetFrameName().c_str(), defaultFocusNode->GetFrameId(), ret); - return ret; - } - if (mainView->GetIsViewRootScopeFocused() && viewRootScope) { - mainView->SetIsViewRootScopeFocused(viewRootScope, true); - auto ret = viewRootScope->RequestFocusImmediately(); - TAG_LOGI(AceLogTag::ACE_FOCUS, - "Target view has no default focus. Request focus on view root: %{public}s/%{public}d return: %{public}d.", - viewRootScope->GetFrameName().c_str(), viewRootScope->GetFrameId(), ret); - return ret; - } - mainView->SetIsViewRootScopeFocused(viewRootScope, false); - auto ret = mainView->RequestFocusImmediately(); - TAG_LOGI(AceLogTag::ACE_FOCUS, - "Target view's default focus has been focused. Request view focus return: %{public}d.", ret); - return ret; -} - bool PipelineContext::RequestFocus(const std::string& targetNodeId) { CHECK_NULL_RETURN(rootNode_, false); @@ -2397,14 +2370,6 @@ void PipelineContext::AddDirtyFocus(const RefPtr& node) RequestFrame(); } -void PipelineContext::AddDirtyDefaultFocus(const RefPtr& node) -{ - CHECK_RUN_ON(UI); - CHECK_NULL_VOID(node); - dirtyDefaultFocusNode_ = WeakPtr(node); - RequestFrame(); -} - void PipelineContext::AddDirtyRequestFocus(const RefPtr& node) { CHECK_RUN_ON(UI); @@ -2610,14 +2575,18 @@ void PipelineContext::WindowFocus(bool isFocus) NotifyPopupDismiss(); } else { TAG_LOGI(AceLogTag::ACE_FOCUS, "Window id: %{public}d get focus.", windowId_); - auto rootFocusHub = rootNode_ ? rootNode_->GetFocusHub() : nullptr; - auto curMainView = FocusHub::GetCurrentMainView(); - if (curMainView && curMainView->GetIsViewHasFocused() && rootFocusHub && !rootFocusHub->IsCurrentFocus()) { - rootFocusHub->RequestFocusImmediately(); + auto curFocusView = focusManager_ ? focusManager_->GetLastFocusView().Upgrade() : nullptr; + auto curFocusViewHub = curFocusView ? curFocusView->GetFocusHub() : nullptr; + if (!curFocusViewHub) { + TAG_LOGW(AceLogTag::ACE_FOCUS, "Current focus view can not found!"); + } else if (curFocusView->GetIsViewHasFocused() && !curFocusViewHub->IsCurrentFocus()) { + TAG_LOGI(AceLogTag::ACE_FOCUS, "Request focus on current focus view: %{public}s/%{public}d", + curFocusView->GetFrameName().c_str(), curFocusView->GetFrameId()); + curFocusViewHub->RequestFocusImmediately(); } if (focusWindowId_.has_value()) { - if (curMainView) { - curMainView->HandleFocusOnMainView(); + if (curFocusView) { + curFocusView->TriggerFocusMove(); } } if (focusOnNodeCallback_) { @@ -2763,6 +2732,7 @@ void PipelineContext::Destroy() overlayManager_.Reset(); sharedTransitionManager_.Reset(); dragDropManager_.Reset(); + focusManager_.Reset(); selectOverlayManager_.Reset(); fullScreenManager_.Reset(); touchEvents_.clear(); @@ -2773,7 +2743,6 @@ void PipelineContext::Destroy() dirtyFocusNode_.Reset(); dirtyFocusScope_.Reset(); needRenderNode_.clear(); - dirtyDefaultFocusNode_.Reset(); dirtyRequestFocusNode_.Reset(); if (textFieldManager_->GetImeShow()) { FocusHub::CloseKeyboard(); diff --git a/frameworks/core/pipeline_ng/pipeline_context.h b/frameworks/core/pipeline_ng/pipeline_context.h index e2543785951..62590f20b5b 100644 --- a/frameworks/core/pipeline_ng/pipeline_context.h +++ b/frameworks/core/pipeline_ng/pipeline_context.h @@ -44,6 +44,7 @@ #ifdef WINDOW_SCENE_SUPPORTED #include "core/components_ng/pattern/ui_extension/ui_extension_manager.h" #endif +#include "core/components_ng/manager/focus/focus_manager.h" #include "core/components_ng/pattern/overlay/overlay_manager.h" #include "core/components_ng/pattern/stage/stage_manager.h" #include "core/components_ng/property/safe_area_insets.h" @@ -323,6 +324,11 @@ public: const RefPtr& GetDragDropManager(); + const RefPtr& GetFocusManager() + { + return focusManager_; + } + const RefPtr& GetFrameRateManager() { return frameRateManager_; @@ -393,10 +399,8 @@ public: bool ChangeMouseStyle(int32_t nodeId, MouseFormat format); - bool RequestDefaultFocus(const RefPtr& mainView); bool RequestFocus(const std::string& targetNodeId) override; void AddDirtyFocus(const RefPtr& node); - void AddDirtyDefaultFocus(const RefPtr& node); void AddDirtyRequestFocus(const RefPtr& node); void RootLostFocus(BlurReason reason = BlurReason::FOCUS_SWITCH) const; @@ -567,6 +571,16 @@ public: return screenNode_.Upgrade(); } + void SetFocusedWindowSceneNode(const RefPtr& node) + { + CHECK_NULL_VOID(node); + windowSceneNode_ = AceType::WeakClaim(AceType::RawPtr(node)); + } + RefPtr GetFocusedWindowSceneNode() const + { + return windowSceneNode_.Upgrade(); + } + void SetJSViewActive(bool active, WeakPtr custom); void UpdateCurrentActiveNode(const WeakPtr& node) override @@ -667,6 +681,8 @@ private: void FlushTouchEvents(); + void FlushFocusView(); + void ProcessDelayTasks(); void InspectDrew(); @@ -768,6 +784,7 @@ private: RefPtr fullScreenManager_; RefPtr selectOverlayManager_; RefPtr dragDropManager_; + RefPtr focusManager_; RefPtr sharedTransitionManager_; #ifdef WINDOW_SCENE_SUPPORTED RefPtr uiExtensionManager_; @@ -778,9 +795,9 @@ private: std::unordered_map touchTestResults_; WeakPtr dirtyFocusNode_; WeakPtr dirtyFocusScope_; - WeakPtr dirtyDefaultFocusNode_; WeakPtr dirtyRequestFocusNode_; WeakPtr screenNode_; + WeakPtr windowSceneNode_; uint32_t nextScheduleTaskId_ = 0; int32_t mouseStyleNodeId_ = -1; uint64_t resampleTimeStamp_ = 0; diff --git a/test/mock/core/pipeline/mock_pipeline_context.cpp b/test/mock/core/pipeline/mock_pipeline_context.cpp index 594072ecb44..afcae140976 100644 --- a/test/mock/core/pipeline/mock_pipeline_context.cpp +++ b/test/mock/core/pipeline/mock_pipeline_context.cpp @@ -312,8 +312,6 @@ void PipelineContext::AddDirtyFocus(const RefPtr& node) {} void PipelineContext::AddDirtyPropertyNode(const RefPtr& dirty) {} -void PipelineContext::AddDirtyDefaultFocus(const RefPtr& node) {} - void PipelineContext::AddDirtyRequestFocus(const RefPtr& node) {} // core/pipeline_ng/pipeline_context.h depends on the specific impl diff --git a/test/unittest/BUILD.gn b/test/unittest/BUILD.gn index 5b5da9a9443..7c9773de3c4 100644 --- a/test/unittest/BUILD.gn +++ b/test/unittest/BUILD.gn @@ -149,6 +149,8 @@ ohos_source_set("ace_components_event") { "$ace_root/frameworks/core/components_ng/event/state_style_manager.cpp", "$ace_root/frameworks/core/components_ng/event/target_component.cpp", "$ace_root/frameworks/core/components_ng/event/touch_event.cpp", + "$ace_root/frameworks/core/components_ng/manager/focus/focus_manager.cpp", + "$ace_root/frameworks/core/components_ng/manager/focus/focus_view.cpp", ] configs = [ ":ace_unittest_config" ] deps = [ "$ace_root/frameworks/core/components/theme:build_theme_code" ] diff --git a/test/unittest/core/common/ace_engine/BUILD.gn b/test/unittest/core/common/ace_engine/BUILD.gn index d91dd252eb6..0dd50403981 100644 --- a/test/unittest/core/common/ace_engine/BUILD.gn +++ b/test/unittest/core/common/ace_engine/BUILD.gn @@ -59,6 +59,8 @@ ohos_unittest("ace_engine_special_test") { "$ace_root/frameworks/core/components_ng/layout/layout_wrapper_node.cpp", "$ace_root/frameworks/core/components_ng/manager/display_sync/ui_display_sync.cpp", "$ace_root/frameworks/core/components_ng/manager/display_sync/ui_display_sync_manager.cpp", + "$ace_root/frameworks/core/components_ng/manager/focus/focus_manager.cpp", + "$ace_root/frameworks/core/components_ng/manager/focus/focus_view.cpp", "$ace_root/frameworks/core/components_ng/manager/frame_rate/frame_rate_manager.cpp", "$ace_root/frameworks/core/components_ng/manager/safe_area/safe_area_manager.cpp", "$ace_root/frameworks/core/components_ng/pattern/custom/custom_node.cpp", diff --git a/test/unittest/core/event/focus_hub_test_ng.cpp b/test/unittest/core/event/focus_hub_test_ng.cpp index 5e3caae3e5b..c01047728d1 100755 --- a/test/unittest/core/event/focus_hub_test_ng.cpp +++ b/test/unittest/core/event/focus_hub_test_ng.cpp @@ -29,6 +29,7 @@ #include "core/components_ng/base/frame_node.h" #include "core/components_ng/event/focus_hub.h" #include "core/components_ng/event/touch_event.h" +#include "core/components_ng/manager/focus/focus_view.h" #include "core/components_ng/pattern/button/button_pattern.h" #include "core/components_ng/pattern/flex/flex_layout_pattern.h" #include "core/components_ng/pattern/pattern.h" @@ -3153,102 +3154,6 @@ HWTEST_F(FocusHubTestNg, FocusHubTestNg0084, TestSize.Level1) EXPECT_FALSE(focusHub->OnKeyEventScope(keyEvent)); } -/** - * @tc.name: FocusHubTestNg0085 - * @tc.desc: Test the function GetMainViewRootScope. - * @tc.type: FUNC - */ -HWTEST_F(FocusHubTestNg, FocusHubTestNg0085, TestSize.Level1) -{ - /** - * @tc.steps: step1. Create FocusHub with the WeakPtr eventHub_ owning frameNode. - * @tc.expected: eventHub can be updated and frameName = V2::DIALOG_ETS_TAG. - */ - auto eventHub = AceType::MakeRefPtr(); - auto frameNode = AceType::MakeRefPtr(V2::DIALOG_ETS_TAG, -1, AceType::MakeRefPtr()); - eventHub->AttachHost(frameNode); - auto focusHub = AceType::MakeRefPtr(eventHub); - EXPECT_TRUE(focusHub->GetFrameNode() != nullptr); - EXPECT_TRUE(focusHub->GetGeometryNode() != nullptr); - EXPECT_EQ(focusHub->GetFrameName(), V2::DIALOG_ETS_TAG); - EXPECT_EQ(focusHub->GetInspectorKey(), std::nullopt); - EXPECT_FALSE(focusHub->GetMainViewRootScope()); -} - -/** - * @tc.name: FocusHubTestNg0086 - * @tc.desc: Test the function GetMainViewRootScope. - * @tc.type: FUNC - */ -HWTEST_F(FocusHubTestNg, FocusHubTestNg0086, TestSize.Level1) -{ - /** - * @tc.steps: step1. Create FocusHub with the WeakPtr eventHub_ owning frameNode. - * @tc.expected: eventHub can be updated and frameName = V2::POPUP_ETS_TAG. - */ - auto eventHub = AceType::MakeRefPtr(); - auto frameNode = AceType::MakeRefPtr(V2::POPUP_ETS_TAG, -1, AceType::MakeRefPtr()); - eventHub->AttachHost(frameNode); - auto focusHub = AceType::MakeRefPtr(eventHub); - EXPECT_TRUE(focusHub->GetFrameNode() != nullptr); - EXPECT_TRUE(focusHub->GetGeometryNode() != nullptr); - EXPECT_EQ(focusHub->GetFrameName(), V2::POPUP_ETS_TAG); - EXPECT_EQ(focusHub->GetInspectorKey(), std::nullopt); - EXPECT_FALSE(focusHub->GetMainViewRootScope()); -} - -/** - * @tc.name: LostFocusToViewRoot0087 - * @tc.desc: Test the function GetCurrentMainView. - * @tc.type: FUNC - */ -HWTEST_F(FocusHubTestNg, FocusHubTestNg0087, TestSize.Level1) -{ - /** - * @tc.steps: step1. Create frameNode. - */ - auto frameNode = FrameNode::CreateFrameNode(V2::ROW_ETS_TAG, 101, AceType::MakeRefPtr()); - auto eventHub = AceType::MakeRefPtr(); - eventHub->AttachHost(frameNode); - auto focusHub = frameNode->GetFocusHub(); - KeyEvent keyEvent; - std::list> focusNodes; - auto itNewFocusNode = focusHub->FlushChildrenFocusHub(focusNodes); - EXPECT_EQ(itNewFocusNode, focusNodes.end()); - auto pipeline = PipelineContext::GetCurrentContext(); - auto screenNode = pipeline->screenNode_ = AceType::WeakClaim(AceType::RawPtr(frameNode)); - EXPECT_FALSE(focusHub->GetCurrentMainView()); -} - -/** - * @tc.name: FocusHubTestNg0088 - * @tc.desc: Test the function GetChildMainView. - * @tc.type: FUNC - */ -HWTEST_F(FocusHubTestNg, FocusHubTestNg0088, TestSize.Level1) -{ - /** - * @tc.steps1: create focusHub and construct allNodes. - */ - auto frameNode = FrameNode::CreateFrameNode(V2::PAGE_ETS_TAG, 101, AceType::MakeRefPtr()); - frameNode->GetOrCreateFocusHub(); - auto focusHub = frameNode->GetFocusHub(); - ASSERT_NE(focusHub, nullptr); - auto frameNode1 = FrameNode::CreateFrameNode(V2::DIALOG_ETS_TAG, 101, AceType::MakeRefPtr()); - frameNode1->GetOrCreateFocusHub(); - auto focusHub1 = frameNode1->GetFocusHub(); - auto frameNode2 = FrameNode::CreateFrameNode(V2::MODAL_PAGE_TAG, 101, AceType::MakeRefPtr()); - frameNode2->GetOrCreateFocusHub(); - auto focusHub2 = frameNode2->GetFocusHub(); - std::list> focusNodes; - auto itNewFocusNode = focusHub->FlushChildrenFocusHub(focusNodes); - EXPECT_EQ(itNewFocusNode, focusNodes.end()); - focusHub->focusType_ = FocusType::SCOPE; - frameNode->children_.push_back(frameNode1); - frameNode->children_.push_back(frameNode2); - EXPECT_TRUE(focusHub->GetChildMainView() != nullptr); -} - /** * @tc.name: FocusHubTestNg0089 * @tc.desc: Test the function IsOnRootTree. @@ -3275,28 +3180,6 @@ HWTEST_F(FocusHubTestNg, FocusHubTestNg0089, TestSize.Level1) ASSERT_FALSE(res); } -/** - * @tc.name: FocusHubTestNg0090 - * @tc.desc: Test the function RequestFocusWithDefaultFocusFirstly. - * @tc.type: FUNC - */ -HWTEST_F(FocusHubTestNg, FocusHubTestNg0090, TestSize.Level1) -{ - /** - * @tc.steps: step1. Create frameNode. - */ - auto frameNode = AceType::MakeRefPtr(V2::MENU_WRAPPER_ETS_TAG, 101, AceType::MakeRefPtr()); - auto child = AceType::MakeRefPtr(V2::MENU_WRAPPER_ETS_TAG, 101, AceType::MakeRefPtr()); - child->GetOrCreateFocusHub(); - frameNode->AddChild(child); - auto eventHub = AceType::MakeRefPtr(); - auto eventHub1 = AceType::MakeRefPtr(); - auto focusHub = AceType::MakeRefPtr(eventHub); - auto focusHub1 = AceType::MakeRefPtr(eventHub1); - focusHub->RequestFocusWithDefaultFocusFirstly(); - ASSERT_TRUE(focusHub->currentFocus_ == false); -} - /** * @tc.name: FocusHubTestNg0091 * @tc.desc: Test the function FocusToHeadOrTailChild. @@ -3423,28 +3306,6 @@ HWTEST_F(FocusHubTestNg, FocusHubTestNg0094, TestSize.Level1) EXPECT_TRUE(focusHub->HandleFocusByTabIndex(keyEvent)); } -/** - * @tc.name: FocusHubTestNg0095 - * @tc.desc: Test the function RequestFocusWithDefaultFocusFirstly. - * @tc.type: FUNC - */ -HWTEST_F(FocusHubTestNg, FocusHubTestNg0095, TestSize.Level1) -{ - /** - * @tc.steps: step1. Create frameNode. - */ - auto eventHub = AceType::MakeRefPtr(); - auto frameNode = AceType::MakeRefPtr(V2::MENU_WRAPPER_ETS_TAG, -1, AceType::MakeRefPtr()); - eventHub->AttachHost(frameNode); - auto focusHub = AceType::MakeRefPtr(eventHub); - EXPECT_TRUE(focusHub->GetFrameNode() != nullptr); - EXPECT_TRUE(focusHub->GetGeometryNode() != nullptr); - EXPECT_EQ(focusHub->GetFrameName(), V2::MENU_WRAPPER_ETS_TAG); - EXPECT_EQ(focusHub->GetInspectorKey(), std::nullopt); - focusHub->RequestFocusWithDefaultFocusFirstly(); - ASSERT_TRUE(focusHub->currentFocus_ == false); -} - /** * @tc.name: FocusHubTestNg0096 * @tc.desc: Test the function OnFocusScope. @@ -3535,41 +3396,6 @@ HWTEST_F(FocusHubTestNg, FocusHubTestNg0098, TestSize.Level1) ASSERT_NE(focusHub->lastWeakFocusNode_.Upgrade(), nullptr); } -/** - * @tc.name: FocusHubTestNg0099 - * @tc.desc: Test the function HandleFocusOnMainView. - * @tc.type: FUNC - */ -HWTEST_F(FocusHubTestNg, FocusHubTestNg0099, TestSize.Level1) -{ - /** - * @tc.steps: step1. Create FocusHub with the WeakPtr eventHub_ owning frameNode. - * @tc.expected: eventHub can be updated and frameName = V2::POPUP_ETS_TAG. - */ - auto frameNode = FrameNode::CreateFrameNode("frameNode", -1, AceType::MakeRefPtr()); - frameNode->GetOrCreateFocusHub(); - auto focusHub = frameNode->GetFocusHub(); - ASSERT_NE(focusHub, nullptr); - auto frameNode1 = FrameNode::CreateFrameNode("frameNode", 101, AceType::MakeRefPtr()); - frameNode1->GetOrCreateFocusHub(); - auto focusHub1 = frameNode1->GetFocusHub(); - frameNode->children_.push_back(frameNode1); - auto rootScope = focusHub->GetChildren().front(); - rootScope->focusType_ = FocusType::SCOPE; - ASSERT_TRUE(focusHub->IsFocusableNode()); - ASSERT_TRUE(focusHub->currentFocus_ == false); - EXPECT_TRUE(focusHub->GetFrameNode() != nullptr); - EXPECT_TRUE(focusHub->GetGeometryNode() != nullptr); - EXPECT_EQ(focusHub->GetFrameName(), "frameNode"); - EXPECT_EQ(focusHub->GetInspectorKey(), std::nullopt); - EXPECT_TRUE(focusHub->GetMainViewRootScope()); - ASSERT_FALSE(focusHub->HandleFocusOnMainView()); - focusHub->GetMainViewRootScope()->currentFocus_ = true; - ASSERT_FALSE(focusHub->HandleFocusOnMainView()); - focusHub->GetMainViewRootScope()->focusDepend_ = FocusDependence::SELF; - ASSERT_TRUE(focusHub->HandleFocusOnMainView()); -} - /** * @tc.name: FocusHubTestNg0100 * @tc.desc: Test the function IsImplicitFocusableScope. diff --git a/test/unittest/core/pattern/overlay/overlay_test_ng.cpp b/test/unittest/core/pattern/overlay/overlay_test_ng.cpp index ffdc763314b..abaa2c3195d 100644 --- a/test/unittest/core/pattern/overlay/overlay_test_ng.cpp +++ b/test/unittest/core/pattern/overlay/overlay_test_ng.cpp @@ -804,7 +804,6 @@ HWTEST_F(OverlayTestNg, MenuTest005, TestSize.Level1) ASSERT_NE(menuPattern, nullptr); auto focusHub = menuWrapperNode->GetOrCreateFocusHub(); ASSERT_NE(focusHub, nullptr); - focusHub->parentFocusable_ = false; menuPattern->SetPreviewMode(MenuPreviewMode::CUSTOM); /** * @tc.steps: step2. call ShowMenuAnimation and call StartShowAnimation of menu pattern @@ -815,7 +814,6 @@ HWTEST_F(OverlayTestNg, MenuTest005, TestSize.Level1) menuWrapperPattern->StartShowAnimation(); pipeline->taskExecutor_ = nullptr; - EXPECT_TRUE(focusHub->parentFocusable_); auto previewPattern = previewNode->GetPattern(); ASSERT_NE(previewPattern, nullptr); EXPECT_TRUE(previewPattern->isFirstShow_); diff --git a/test/unittest/core/pattern/plugin/BUILD.gn b/test/unittest/core/pattern/plugin/BUILD.gn index d185c385bb7..8dba93765c1 100644 --- a/test/unittest/core/pattern/plugin/BUILD.gn +++ b/test/unittest/core/pattern/plugin/BUILD.gn @@ -73,6 +73,8 @@ ohos_unittest("plugin_pattern_test_ng") { "$ace_root/frameworks/core/components_ng/layout/layout_wrapper.cpp", "$ace_root/frameworks/core/components_ng/layout/layout_wrapper_builder.cpp", "$ace_root/frameworks/core/components_ng/layout/layout_wrapper_node.cpp", + "$ace_root/frameworks/core/components_ng/manager/focus/focus_manager.cpp", + "$ace_root/frameworks/core/components_ng/manager/focus/focus_view.cpp", "$ace_root/frameworks/core/components_ng/manager/safe_area/safe_area_manager.cpp", "$ace_root/frameworks/core/components_ng/pattern/custom/custom_node.cpp", "$ace_root/frameworks/core/components_ng/pattern/flex/flex_layout_algorithm.cpp", diff --git a/test/unittest/core/pipeline/pipeline_context_test_ng.cpp b/test/unittest/core/pipeline/pipeline_context_test_ng.cpp index 83bda98521a..21defc90b53 100644 --- a/test/unittest/core/pipeline/pipeline_context_test_ng.cpp +++ b/test/unittest/core/pipeline/pipeline_context_test_ng.cpp @@ -53,6 +53,7 @@ #include "core/components_ng/base/frame_node.h" #include "core/components_ng/event/event_hub.h" #include "core/components_ng/event/focus_hub.h" +#include "core/components_ng/manager/focus/focus_view.h" #include "core/components_ng/pattern/bubble/bubble_pattern.h" #include "core/components_ng/pattern/button/button_event_hub.h" #include "core/components_ng/pattern/container_modal/container_modal_pattern.h" @@ -366,7 +367,7 @@ HWTEST_F(PipelineContextTestNg, PipelineContextTestNg004, TestSize.Level1) /** * @tc.name: PipelineContextTestNg005 - * @tc.desc: Test the function FlushFocus and RequestDefaultFocus. + * @tc.desc: Test the function FlushFocus. * @tc.type: FUNC */ HWTEST_F(PipelineContextTestNg, PipelineContextTestNg005, TestSize.Level1) @@ -418,76 +419,6 @@ HWTEST_F(PipelineContextTestNg, PipelineContextTestNg005, TestSize.Level1) frameNode_->eventHub_->focusHub_ = nullptr; context_->FlushFocus(); EXPECT_EQ(context_->dirtyFocusNode_.Upgrade(), nullptr); - - /** - * @tc.steps5: set stageManager_ and stageNode_, stageNode_'s child, - create frameNode_1's focusHub and call SetIsDefaultHasFocused with true - * @tc.expected: RequestDefaultFocus returns false. - */ - context_->stageManager_->stageNode_ = frameNode_; - frameNodeId_ = ElementRegister::GetInstance()->MakeUniqueId(); - auto frameNode_1 = FrameNode::GetOrCreateFrameNode(TEST_TAG, frameNodeId_, nullptr); - frameNode_->children_.push_back(frameNode_1); - focusHub = frameNode_1->eventHub_->GetOrCreateFocusHub(); - focusHub->SetIsDefaultHasFocused(true); - EXPECT_FALSE(context_->RequestDefaultFocus(focusHub)); - /** - * @tc.steps6: call SetIsDefaultHasFocused with false and create a new frameNode - init frameNode_2's focusHub - * @tc.expected: RequestDefaultFocus returns true while IsFocusableWholePath return true - RequestDefaultFocus returns false while IsFocusableWholePath return false. - */ - focusHub->SetFocusType(FocusType::SCOPE); - focusHub->focusable_ = true; - focusHub->SetIsDefaultHasFocused(false); - auto frameNodeId_2 = ElementRegister::GetInstance()->MakeUniqueId(); - auto frameNode_2 = FrameNode::GetOrCreateFrameNode(TEST_TAG, frameNodeId_2, nullptr); - frameNode_1->children_.push_back(frameNode_2); - frameNode_2->parent_ = frameNode_1; - auto newFocusHub = frameNode_2->eventHub_->GetOrCreateFocusHub(); - newFocusHub->SetIsDefaultFocus(true); - newFocusHub->SetFocusType(FocusType::NODE); - frameNode_2->eventHub_->enabled_ = true; - newFocusHub->focusable_ = true; - newFocusHub->parentFocusable_ = true; - EXPECT_TRUE(context_->RequestDefaultFocus(focusHub)); - focusHub->SetIsDefaultHasFocused(false); - focusHub->currentFocus_ = false; - focusHub->focusable_ = false; - newFocusHub->currentFocus_ = false; - newFocusHub->focusable_ = false; - EXPECT_FALSE(context_->RequestDefaultFocus(focusHub)); - - /** - * @tc.steps7: Create a new frameNode and call AddDirtyDefaultFocus - * @tc.expected: dirtyDefaultFocusNode_ is null - */ - auto frameNodeId_3 = ElementRegister::GetInstance()->MakeUniqueId(); - auto frameNode_3 = FrameNode::GetOrCreateFrameNode(TEST_TAG, frameNodeId_3, nullptr); - eventHub = frameNode_3->GetEventHub(); - eventHub->SetEnabled(true); - - focusHub = eventHub->GetOrCreateFocusHub(); - focusHub->SetFocusType(FocusType::NODE); - focusHub->SetIsDefaultFocus(true); - - context_->AddDirtyDefaultFocus(frameNode_3); - EXPECT_FALSE(context_->dirtyDefaultFocusNode_.Invalid()); - context_->FlushFocus(); - EXPECT_TRUE(context_->dirtyDefaultFocusNode_.Invalid()); - EXPECT_FALSE(context_->dirtyFocusNode_.Upgrade()); - EXPECT_FALSE(context_->dirtyFocusScope_.Upgrade()); - - auto frameNodeId_4 = ElementRegister::GetInstance()->MakeUniqueId(); - auto frameNode_4 = FrameNode::GetOrCreateFrameNode(TEST_TAG, frameNodeId_4, nullptr); - auto eventHubRoot = frameNode_4->GetEventHub(); - auto focusHubRoot = eventHubRoot->GetOrCreateFocusHub(); - focusHubRoot->currentFocus_ = true; - focusHub->SetFocusType(FocusType::NODE); - - context_->rootNode_ = frameNode_4; - context_->FlushFocus(); - EXPECT_TRUE(focusHubRoot->IsCurrentFocus()); } /** -- Gitee