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