• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2024 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "core/components_ng/manager/focus/focus_view.h"
17 
18 #include "base/memory/ace_type.h"
19 #include "base/memory/referenced.h"
20 #include "core/event/key_event.h"
21 #include "core/pipeline_ng/pipeline_context.h"
22 
23 namespace OHOS::Ace::NG {
24 
FocusViewShow(bool isTriggerByStep)25 void FocusView::FocusViewShow(bool isTriggerByStep)
26 {
27     if (GetFrameName() == V2::NAVBAR_ETS_TAG ||
28         GetFrameName() == V2::NAVDESTINATION_VIEW_ETS_TAG ||
29         GetFrameName() == V2::MENU_ETS_TAG) {
30         if (!GetFocusViewFocusable()) {
31             TAG_LOGI(AceLogTag::ACE_FOCUS, "Focus view: %{public}s/%{public}d is not focusable, cannot be shown",
32                 GetFrameName().c_str(), GetFrameId());
33             return;
34         }
35     }
36     TAG_LOGI(AceLogTag::ACE_FOCUS, "Focus view: %{public}s/%{public}d show", GetFrameName().c_str(), GetFrameId());
37     auto viewRootScope = GetViewRootScope();
38     if (viewRootScope && GetIsViewRootScopeFocused()) {
39         viewRootScope->SetFocusDependence(FocusDependence::SELF);
40     }
41     isViewHasFocused_ = false;
42     auto node = GetFrameNode();
43     CHECK_NULL_VOID(node);
44     auto pipeline = node->GetContextRefPtr();
45     CHECK_NULL_VOID(pipeline);
46     auto focusManager = pipeline->GetFocusManager();
47     CHECK_NULL_VOID(focusManager);
48     focusManager->FocusViewShow(AceType::Claim(this), isTriggerByStep);
49     pipeline->RequestFrame();
50 }
51 
FocusViewHide()52 void FocusView::FocusViewHide()
53 {
54     TAG_LOGI(AceLogTag::ACE_FOCUS, "Focus view: %{public}s/%{public}d hide", GetFrameName().c_str(), GetFrameId());
55     auto node = GetFrameNode();
56     CHECK_NULL_VOID(node);
57     auto pipeline = node->GetContextRefPtr();
58     CHECK_NULL_VOID(pipeline);
59     auto focusManager = pipeline->GetFocusManager();
60     CHECK_NULL_VOID(focusManager);
61     focusManager->FocusViewHide(AceType::Claim(this));
62     pipeline->RequestFrame();
63 }
64 
FocusViewClose()65 void FocusView::FocusViewClose()
66 {
67     if (!isViewHasShow_) {
68         TAG_LOGI(AceLogTag::ACE_FOCUS, "Focus view: %{public}s/%{public}d has not been shown",
69             GetFrameName().c_str(), GetFrameId());
70         return;
71     }
72     TAG_LOGI(AceLogTag::ACE_FOCUS, "Focus view: %{public}s/%{public}d close", GetFrameName().c_str(), GetFrameId());
73     auto node = GetFrameNode();
74     CHECK_NULL_VOID(node);
75     auto pipeline = node->GetContextRefPtr();
76     CHECK_NULL_VOID(pipeline);
77     auto focusManager = pipeline->GetFocusManager();
78     CHECK_NULL_VOID(focusManager);
79     focusManager->FocusViewClose(AceType::Claim(this));
80     pipeline->RequestFrame();
81 }
82 
GetFrameNode()83 RefPtr<FrameNode> FocusView::GetFrameNode()
84 {
85     auto focusViewPattern = AceType::DynamicCast<Pattern>(AceType::Claim(this));
86     CHECK_NULL_RETURN(focusViewPattern, nullptr);
87     return focusViewPattern->GetHost();
88 }
89 
GetFrameName()90 std::string FocusView::GetFrameName()
91 {
92     auto focusViewPattern = AceType::DynamicCast<Pattern>(AceType::Claim(this));
93     CHECK_NULL_RETURN(focusViewPattern, "NULL");
94     auto focusViewFrame = focusViewPattern->GetHost();
95     CHECK_NULL_RETURN(focusViewFrame, "NULL");
96     return focusViewFrame->GetTag();
97 }
98 
GetFrameId()99 int32_t FocusView::GetFrameId()
100 {
101     auto focusViewPattern = AceType::DynamicCast<Pattern>(AceType::Claim(this));
102     CHECK_NULL_RETURN(focusViewPattern, -1);
103     auto focusViewFrame = focusViewPattern->GetHost();
104     CHECK_NULL_RETURN(focusViewFrame, -1);
105     return focusViewFrame->GetId();
106 }
107 
LostViewFocus()108 void FocusView::LostViewFocus()
109 {
110     TAG_LOGI(
111         AceLogTag::ACE_FOCUS, "Focus view: %{public}s/%{public}d lost focus", GetFrameName().c_str(), GetFrameId());
112     auto focusViewHub = GetFocusHub();
113     CHECK_NULL_VOID(focusViewHub);
114     if (focusViewHub->IsCurrentFocus()) {
115         focusViewHub->LostFocus(BlurReason::VIEW_SWITCH);
116     }
117 }
118 
GetFocusHub()119 RefPtr<FocusHub> FocusView::GetFocusHub()
120 {
121     auto focusViewPattern = AceType::DynamicCast<Pattern>(AceType::Claim(this));
122     CHECK_NULL_RETURN(focusViewPattern, nullptr);
123     auto focusViewFrame = focusViewPattern->GetHost();
124     CHECK_NULL_RETURN(focusViewFrame, nullptr);
125     auto focusViewHub = focusViewFrame->GetFocusHub();
126     return focusViewHub;
127 }
128 
GetCurrentFocusView()129 RefPtr<FocusView> FocusView::GetCurrentFocusView()
130 {
131     auto pipeline = PipelineContext::GetCurrentContextSafely();
132     CHECK_NULL_RETURN(pipeline, nullptr);
133     auto focusManager = pipeline->GetFocusManager();
134     CHECK_NULL_RETURN(focusManager, nullptr);
135     return focusManager->GetLastFocusView().Upgrade();
136 }
137 
GetEntryFocusView()138 RefPtr<FocusView> FocusView::GetEntryFocusView()
139 {
140     if (IsEntryFocusView()) {
141         return AceType::Claim(this);
142     }
143     auto focusViewHub = GetFocusHub();
144     auto parentFocusHub = focusViewHub ? focusViewHub->GetParentFocusHub() : nullptr;
145     while (parentFocusHub) {
146         auto parentFrame = parentFocusHub->GetFrameNode();
147         auto parentFocusView = parentFrame ? parentFrame->GetPattern<FocusView>() : nullptr;
148         if (!parentFocusView) {
149             parentFocusHub = parentFocusHub->GetParentFocusHub();
150             continue;
151         }
152         if (parentFocusView->IsEntryFocusView()) {
153             return parentFocusView;
154         }
155         parentFocusHub = parentFocusHub->GetParentFocusHub();
156     }
157     return AceType::Claim(this);
158 }
159 
GetViewRootScope()160 RefPtr<FocusHub> FocusView::GetViewRootScope()
161 {
162     auto rootScopeSpecified = rootScopeSpecified_.Upgrade();
163     if (rootScopeSpecified) {
164         return rootScopeSpecified;
165     }
166     auto focusViewPattern = AceType::DynamicCast<Pattern>(AceType::Claim(this));
167     CHECK_NULL_RETURN(focusViewPattern, nullptr);
168     auto focusViewFrame = focusViewPattern->GetHost();
169     CHECK_NULL_RETURN(focusViewFrame, nullptr);
170     auto focusViewHub = focusViewFrame->GetFocusHub();
171     CHECK_NULL_RETURN(focusViewHub, nullptr);
172     std::list<int32_t> rootScopeDeepth = GetRouteOfFirstScope();
173     RefPtr<FocusHub> rootScope = focusViewHub;
174     for (const auto& index : rootScopeDeepth) {
175         CHECK_NULL_RETURN(rootScope, focusViewHub);
176         auto children = rootScope->GetChildren();
177         auto iter = children.begin();
178         std::advance(iter, index);
179         if (iter == children.end()) {
180             TAG_LOGD(AceLogTag::ACE_FOCUS, "Index: %{public}d of %{public}s/%{public}d 's children is invalid.", index,
181                 rootScope->GetFrameName().c_str(), rootScope->GetFrameId());
182             return focusViewHub;
183         }
184         rootScope = *iter;
185     }
186     CHECK_NULL_RETURN(rootScope, nullptr);
187     auto node = GetFrameNode();
188     CHECK_NULL_RETURN(node, nullptr);
189     auto pipeline = node->GetContextRefPtr();
190     auto screenNode = pipeline ? pipeline->GetScreenNode() : nullptr;
191     auto screenFocusHub = screenNode ? screenNode->GetFocusHub() : nullptr;
192     if (rootScope->GetFocusType() != FocusType::SCOPE || (screenFocusHub && rootScope == screenFocusHub)) {
193         rootScope = rootScope->GetParentFocusHub();
194     }
195     if (rootScope != focusViewHub) {
196         focusViewHub->SetFocusDependence(FocusDependence::AUTO);
197     }
198     return rootScope;
199 }
200 
SetIsViewRootScopeFocused(bool isViewRootScopeFocused)201 void FocusView::SetIsViewRootScopeFocused(bool isViewRootScopeFocused)
202 {
203     isViewRootScopeFocused_ = isViewRootScopeFocused;
204     auto viewRootScope = GetViewRootScope();
205     CHECK_NULL_VOID(viewRootScope);
206     viewRootScope->SetFocusDependence(isViewRootScopeFocused ? FocusDependence::SELF : FocusDependence::AUTO);
207 }
208 
IsRootScopeCurrentFocus()209 bool FocusView::IsRootScopeCurrentFocus()
210 {
211     auto viewRootScope = GetViewRootScope();
212     return viewRootScope ? viewRootScope->IsCurrentFocus() : false;
213 }
214 
IsChildFocusViewOf(const RefPtr<FocusView> & parent)215 bool FocusView::IsChildFocusViewOf(const RefPtr<FocusView>& parent)
216 {
217     auto focusViewHub = GetFocusHub();
218     auto parentFocusHub = focusViewHub ? focusViewHub->GetParentFocusHub() : nullptr;
219     while (parentFocusHub) {
220         auto parentFrame = parentFocusHub->GetFrameNode();
221         auto parentFocusView = parentFrame ? parentFrame->GetPattern<FocusView>() : nullptr;
222         if (!parentFocusView) {
223             parentFocusHub = parentFocusHub->GetParentFocusHub();
224             continue;
225         }
226         if (parentFocusView == parent) {
227             return true;
228         }
229         parentFocusHub = parentFocusHub->GetParentFocusHub();
230     }
231     return false;
232 }
233 
HasParentFocusHub()234 bool FocusView::HasParentFocusHub()
235 {
236     auto focusViewHub = GetFocusHub();
237     CHECK_NULL_RETURN(focusViewHub, false);
238     return focusViewHub->GetParentFocusHub() != nullptr;
239 }
240 
RequestDefaultFocus()241 bool FocusView::RequestDefaultFocus()
242 {
243     TAG_LOGI(AceLogTag::ACE_FOCUS, "Request focus on focus view: %{public}s/%{public}d.", GetFrameName().c_str(),
244         GetFrameId());
245     auto focusViewHub = GetFocusHub();
246     CHECK_NULL_RETURN(focusViewHub, false);
247     if (focusViewHub->GetFocusType() != FocusType::SCOPE || !focusViewHub->IsFocusableNode()) {
248         return false;
249     }
250     auto viewRootScope = GetViewRootScope();
251     CHECK_NULL_RETURN(viewRootScope, false);
252     isViewHasFocused_ = true;
253     auto defaultFocusNode = focusViewHub->GetChildFocusNodeByType(FocusNodeType::DEFAULT);
254 
255     auto isViewRootScopeHasChildFocused = viewRootScope->HasFocusedChild();
256     if (neverShown_ && !isViewRootScopeHasChildFocused) {
257         if (!defaultFocusNode) {
258             TAG_LOGI(AceLogTag::ACE_FOCUS, "Focus view has no default focus.");
259         } else if (!defaultFocusNode->IsFocusableWholePath()) {
260             TAG_LOGI(AceLogTag::ACE_FOCUS, "Default focus node: %{public}s/%{public}d is not focusable",
261                 defaultFocusNode->GetFrameName().c_str(), defaultFocusNode->GetFrameId());
262         } else {
263             SetIsViewRootScopeFocused(false);
264             auto ret = defaultFocusNode->RequestFocusImmediatelyInner();
265             FocusViewDidShow(defaultFocusNode);
266             TAG_LOGI(AceLogTag::ACE_FOCUS, "Request focus on default focus: %{public}s/%{public}d return: %{public}d.",
267                 defaultFocusNode->GetFrameName().c_str(), defaultFocusNode->GetFrameId(), ret);
268             return ret;
269         }
270     }
271     if (isViewRootScopeFocused_ && viewRootScope) {
272         SetIsViewRootScopeFocused(true);
273         auto ret = viewRootScope->RequestFocusImmediatelyInner();
274         TAG_LOGI(AceLogTag::ACE_FOCUS, "Request focus on view root scope: %{public}s/%{public}d return: %{public}d.",
275             viewRootScope->GetFrameName().c_str(), viewRootScope->GetFrameId(), ret);
276         return ret;
277     }
278     SetIsViewRootScopeFocused(false);
279     bool ret = false;
280     if (focusViewHub->IsCurrentFocus()) {
281         focusViewHub->InheritFocus();
282         ret = true;
283     } else {
284         ret = focusViewHub->RequestFocusImmediatelyInner();
285     }
286     TAG_LOGI(AceLogTag::ACE_FOCUS, "Request focus on focus view return: %{public}d.", ret);
287     return ret;
288 }
289 
TriggerFocusMove()290 bool FocusView::TriggerFocusMove()
291 {
292     TAG_LOGI(AceLogTag::ACE_FOCUS, "Focus view: %{public}s/%{public}d trigger focus move.", GetFrameName().c_str(),
293         GetFrameId());
294     auto viewRootScope = GetViewRootScope();
295     CHECK_NULL_RETURN(viewRootScope, false);
296     if (!viewRootScope->IsCurrentFocus()) {
297         TAG_LOGI(AceLogTag::ACE_FOCUS,
298             "Current view root: %{public}s/%{public}d is not on focusing. Cannot trigger focus move.",
299             viewRootScope->GetFrameName().c_str(), viewRootScope->GetFrameId());
300         return false;
301     }
302     if (viewRootScope->GetFocusDependence() != FocusDependence::SELF) {
303         TAG_LOGI(AceLogTag::ACE_FOCUS,
304             "Current view root: %{public}s/%{public}d is not focus depend self. Do not trigger focus move.",
305             viewRootScope->GetFrameName().c_str(), viewRootScope->GetFrameId());
306         return false;
307     }
308 
309     auto viewFocusHub = GetFocusHub();
310     CHECK_NULL_RETURN(viewFocusHub, false);
311     TabIndexNodeList tabIndexNodes;
312     tabIndexNodes.clear();
313     viewFocusHub->CollectTabIndexNodes(tabIndexNodes);
314     if (tabIndexNodes.empty()) {
315         // No tabIndex node in current main view. Extend focus from viewRootScope to children.
316         FocusViewDidShow(viewFocusHub);
317         SetIsViewRootScopeFocused(false);
318         viewRootScope->InheritFocus();
319         return true;
320     }
321 
322     // First tabIndex node need get focus.
323     tabIndexNodes.sort([](std::pair<int32_t, WeakPtr<FocusHub>>& a, std::pair<int32_t, WeakPtr<FocusHub>>& b) {
324         return a.first < b.first;
325     });
326     return viewFocusHub->GoToFocusByTabNodeIdx(tabIndexNodes, 0);
327 }
328 
GetFocusViewFocusable()329 bool FocusView::GetFocusViewFocusable()
330 {
331     auto focusViewHub = GetFocusHub();
332     CHECK_NULL_RETURN(focusViewHub, false);
333     if (!focusViewHub->IsSelfFocusableWholePath()) {
334         return false;
335     }
336     return true;
337 }
338 
FocusViewDidShow(const RefPtr<FocusHub> & focusHub)339 void FocusView::FocusViewDidShow(const RefPtr<FocusHub>& focusHub)
340 {
341     if (!focusHub) {
342         TAG_LOGI(AceLogTag::ACE_FOCUS, "Focus view: %{public}s/%{public}d reset shown flag.",
343             GetFrameName().c_str(), GetFrameId());
344         neverShown_ = false;
345         return;
346     }
347     RefPtr<UINode> node = focusHub->GetFrameNode();
348     do {
349         auto frameNode = DynamicCast<FrameNode>(node);
350         if (frameNode) {
351             auto focusView = frameNode->GetPattern<FocusView>();
352             if (focusView) {
353                 if (focusView->neverShown_) {
354                     TAG_LOGI(AceLogTag::ACE_FOCUS, "Focus view: %{public}s/%{public}d is first shown.",
355                         focusView->GetFrameName().c_str(), focusView->GetFrameId());
356                     focusView->neverShown_ = false;
357                 } else {
358                     return;
359                 }
360             }
361         }
362         node = node->GetParent();
363     } while (node);
364 }
365 } // namespace OHOS::Ace::NG
366