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_manager.h"
17
18 #include "base/log/dump_log.h"
19 #include "base/subwindow/subwindow_manager.h"
20 #include "core/components/theme/app_theme.h"
21 #include "core/pipeline_ng/pipeline_context.h"
22
23 namespace OHOS::Ace::NG {
24 namespace {
GetCurrentFocusManager()25 RefPtr<FocusManager> GetCurrentFocusManager()
26 {
27 auto context = NG::PipelineContext::GetCurrentContextSafely();
28 CHECK_NULL_RETURN(context, nullptr);
29 auto focusManager = context->GetFocusManager();
30 return focusManager;
31 }
32 }
33
FocusManager(const RefPtr<PipelineContext> & pipeline)34 FocusManager::FocusManager(const RefPtr<PipelineContext>& pipeline): pipeline_(pipeline)
35 {
36 CHECK_NULL_VOID(pipeline);
37 if (pipeline->GetRootElement()) {
38 currentFocus_ = pipeline->GetRootElement()->GetFocusHub();
39 }
40 // After switching between portrait and landscape mode
41 // reset the isNeedTriggerScroll parameter to enable screen focus scrolling.
42 pipeline->RegisterSurfaceChangedCallback([weak = WeakClaim(this)](int32_t width, int32_t height, int32_t oldWidth,
43 int32_t oldHeight, WindowSizeChangeReason type) {
44 auto context = weak.Upgrade();
45 context->SetNeedTriggerScroll(true);
46 });
47 }
48
FocusViewShow(const RefPtr<FocusView> & focusView,bool isTriggerByStep)49 void FocusManager::FocusViewShow(const RefPtr<FocusView>& focusView, bool isTriggerByStep)
50 {
51 CHECK_NULL_VOID(focusView);
52 if (!focusView->HasParentFocusHub()) {
53 TAG_LOGD(AceLogTag::ACE_FOCUS, "FocusView: %{public}s/%{public}d has no parent. Do not need show.",
54 focusView->GetFrameName().c_str(), focusView->GetFrameId());
55 return;
56 }
57 focusView->SetIsViewHasShow(true);
58 auto lastFocusView = lastFocusView_.Upgrade();
59 if (lastFocusView) {
60 if (lastFocusView == focusView || lastFocusView->IsChildFocusViewOf(focusView)) {
61 return;
62 }
63 if (!focusView->IsChildFocusViewOf(lastFocusView) && IsAutoFocusTransfer()) {
64 lastFocusView->LostViewFocus();
65 }
66 }
67
68 auto focusViewWeak = AceType::WeakClaim(AceType::RawPtr(focusView));
69 if (std::find(focusViewStack_.begin(), focusViewStack_.end(), focusViewWeak) != focusViewStack_.end()) {
70 focusViewStack_.remove(focusViewWeak);
71 }
72 focusViewStack_.emplace_back(focusViewWeak);
73 focusViewStackState_ = FocusViewStackState::SHOW;
74 lastFocusView_ = focusViewWeak;
75
76 // do not set LastWeakFocus to Previous node/scope in focusView when FocusViewShow trigger by FocusStep
77 if (!isTriggerByStep) {
78 lastFocusView = lastFocusView_.Upgrade();
79 if (!lastFocusView) {
80 return;
81 }
82 auto lastFocusViewHub = lastFocusView->GetFocusHub();
83 if (lastFocusViewHub) {
84 lastFocusViewHub->SetLastWeakFocusToPreviousInFocusView();
85 }
86 }
87 }
88
RearrangeViewStack()89 bool FocusManager::RearrangeViewStack()
90 {
91 auto curFocusView = FocusView::GetCurrentFocusView();
92 CHECK_NULL_RETURN(curFocusView, false);
93 auto curFocusViewHub = curFocusView->GetFocusHub();
94 CHECK_NULL_RETURN(curFocusViewHub, false);
95 auto curFocusViewWeak = AceType::WeakClaim(AceType::RawPtr(curFocusView));
96 if (!curFocusViewHub->IsCurrentFocus() && focusViewStackState_ == FocusViewStackState::SHOW) {
97 if (std::find(focusViewStack_.begin(), focusViewStack_.end(), curFocusViewWeak) != focusViewStack_.end()) {
98 focusViewStack_.remove(curFocusViewWeak);
99 }
100 lastFocusView_ = focusViewStack_.back();
101 return true;
102 }
103 if (focusViewStackState_ == FocusViewStackState::CLOSE) {
104 auto ret = SetFocusViewRootScope(curFocusView);
105 return ret;
106 }
107 return false;
108 }
109
FocusViewHide(const RefPtr<FocusView> & focusView)110 void FocusManager::FocusViewHide(const RefPtr<FocusView>& focusView)
111 {
112 CHECK_NULL_VOID(focusView);
113 if (IsAutoFocusTransfer()) {
114 focusView->LostViewFocus();
115 }
116 auto lastFocusView = lastFocusView_.Upgrade();
117 if (lastFocusView && (lastFocusView == focusView || lastFocusView->IsChildFocusViewOf(focusView))) {
118 lastFocusView_ = nullptr;
119 }
120 }
121
FocusViewClose(const RefPtr<FocusView> & focusView,bool isDetachFromTree)122 void FocusManager::FocusViewClose(const RefPtr<FocusView>& focusView, bool isDetachFromTree)
123 {
124 if (!IsAutoFocusTransfer() && !isDetachFromTree) {
125 return;
126 }
127 CHECK_NULL_VOID(focusView);
128 focusView->LostViewFocus();
129 focusView->SetIsViewHasShow(false);
130 for (auto iter = focusViewStack_.begin(); iter != focusViewStack_.end();) {
131 auto view = (*iter).Upgrade();
132 if (view && (view == focusView || view->IsChildFocusViewOf(focusView))) {
133 auto focusHub = view->GetFocusHub();
134 if (focusHub) {
135 focusHub->RemoveFocusScopeIdAndPriority();
136 }
137 iter = focusViewStack_.erase(iter);
138 focusViewStackState_ = FocusViewStackState::CLOSE;
139 } else {
140 ++iter;
141 }
142 }
143 if (focusViewStack_.empty()) {
144 lastFocusView_ = nullptr;
145 TAG_LOGW(AceLogTag::ACE_FOCUS, "viewStack empty");
146 return;
147 }
148 if (focusViewStack_.back() != lastFocusView_) {
149 lastFocusView_ = focusViewStack_.back();
150 auto lastFocusView = lastFocusView_.Upgrade();
151 CHECK_NULL_VOID(lastFocusView);
152 auto lastFocusViewHub = lastFocusView->GetFocusHub();
153 CHECK_NULL_VOID(lastFocusViewHub);
154 if (!lastFocusViewHub->IsFocusableNode()) {
155 TAG_LOGW(AceLogTag::ACE_FOCUS,
156 "unfocusable view:%{public}s enable:%{public}d show:%{public}d focusable:%{public}d",
157 lastFocusViewHub->GetFrameName().c_str(), lastFocusViewHub->IsEnabled(), lastFocusViewHub->IsShow(),
158 lastFocusViewHub->focusable_);
159 }
160 }
161 }
162
FlushFocusView()163 void FocusManager::FlushFocusView()
164 {
165 auto lastFocusView = lastFocusView_.Upgrade();
166 auto lastFocusViewHub = lastFocusView ? lastFocusView->GetFocusHub() : nullptr;
167 if (lastFocusViewHub && lastFocusViewHub->IsCurrentFocus()) {
168 return;
169 }
170 RefPtr<FocusView> currFocusView = nullptr;
171 for (const auto& weakView : focusViewStack_) {
172 auto view = weakView.Upgrade();
173 auto viewHub = view ? view->GetFocusHub() : nullptr;
174 if (!viewHub || !viewHub->IsCurrentFocus()) {
175 continue;
176 }
177 if (currFocusView && currFocusView->IsChildFocusViewOf(view)) {
178 continue;
179 }
180 currFocusView = view;
181 }
182 lastFocusView_ = currFocusView ? AceType::WeakClaim(AceType::RawPtr(currFocusView)) : nullptr;
183 }
184
GetFocusViewMap(FocusViewMap & focusViewMap)185 void FocusManager::GetFocusViewMap(FocusViewMap& focusViewMap)
186 {
187 for (const auto& focusViewWeak : focusViewStack_) {
188 auto focusView = focusViewWeak.Upgrade();
189 if (!focusView) {
190 continue;
191 }
192 auto focusViewId = focusView->GetFrameId();
193 auto entryFocusView = focusView->GetEntryFocusView();
194 if (entryFocusView && entryFocusView != focusView) {
195 auto entryFocusViewId = entryFocusView->GetFrameId();
196 auto entryFocusViewWeak = AceType::WeakClaim(AceType::RawPtr(entryFocusView));
197 auto iter = focusViewMap.find(entryFocusViewId);
198 if (iter == focusViewMap.end()) {
199 focusViewMap[entryFocusViewId] = { entryFocusViewWeak, { focusViewWeak } };
200 } else {
201 iter->second.second.emplace_back(focusViewWeak);
202 }
203 } else {
204 focusViewMap[focusViewId] = { focusViewWeak, {} };
205 }
206 }
207 }
208
PaintFocusState()209 void FocusManager::PaintFocusState()
210 {
211 auto pipeline = pipeline_.Upgrade();
212 CHECK_NULL_VOID(pipeline);
213 auto rootNode = pipeline->GetRootElement();
214 CHECK_NULL_VOID(rootNode);
215 auto rootFocusHub = rootNode->GetFocusHub();
216 CHECK_NULL_VOID(rootFocusHub);
217 if (!pipeline->GetIsFocusActive()) {
218 return;
219 }
220 rootFocusHub->ClearAllFocusState();
221 rootFocusHub->PaintAllFocusState();
222 }
223
224
DumpFocusManager()225 void FocusManager::DumpFocusManager()
226 {
227 if (!DumpLog::GetInstance().GetDumpFile()) {
228 return;
229 }
230 DumpLog::GetInstance().Print("Focus view:");
231 std::unordered_map<int32_t, std::pair<WeakPtr<FocusView>, std::list<WeakPtr<FocusView>>>> focusViewMap;
232 GetFocusViewMap(focusViewMap);
233 for (const auto& focusViewInfo : focusViewMap) {
234 auto focusView = focusViewInfo.second.first.Upgrade();
235 if (!focusView) {
236 continue;
237 }
238 auto childFocusViewWeakList = focusViewInfo.second.second;
239 bool isFocusedView = false;
240 auto lastFocusView = lastFocusView_.Upgrade();
241 auto lastEntryFocusView = lastFocusView ? lastFocusView->GetEntryFocusView() : nullptr;
242 if (focusView == lastEntryFocusView) {
243 isFocusedView = true;
244 }
245 std::string information = focusView->GetFrameName();
246 information += isFocusedView ? "(*)" : "";
247 information += " id:" + std::to_string(focusView->GetFrameId());
248 DumpLog::GetInstance().Print(0, information, static_cast<int32_t>(childFocusViewWeakList.size()));
249 for (const auto& childWeak : childFocusViewWeakList) {
250 auto child = childWeak.Upgrade();
251 if (!child) {
252 continue;
253 }
254 std::string childInformation = child->GetFrameName();
255 childInformation += child == lastFocusView ? "(*)" : "";
256 childInformation += " id:" + std::to_string(child->GetFrameId());
257 DumpLog::GetInstance().Print(1, childInformation, 0);
258 }
259 }
260 }
261
AddFocusScope(const std::string & focusScopeId,const RefPtr<FocusHub> & scopeFocusHub)262 bool FocusManager::AddFocusScope(const std::string& focusScopeId, const RefPtr<FocusHub>& scopeFocusHub)
263 {
264 auto iter = focusHubScopeMap_.find(focusScopeId);
265 if (iter != focusHubScopeMap_.end()) {
266 auto focusScope = iter->second.first.Upgrade();
267 if (!focusScope) {
268 iter->second.first = scopeFocusHub;
269 return true;
270 }
271 return false;
272 } else {
273 focusHubScopeMap_[focusScopeId] = { scopeFocusHub, {} };
274 }
275 return true;
276 }
277
RemoveFocusScope(const std::string & focusScopeId)278 void FocusManager::RemoveFocusScope(const std::string& focusScopeId)
279 {
280 auto iter = focusHubScopeMap_.find(focusScopeId);
281 if (iter != focusHubScopeMap_.end()) {
282 if (iter->second.second.empty()) {
283 focusHubScopeMap_.erase(iter);
284 } else {
285 iter->second.first = nullptr;
286 }
287 }
288 }
289
AddScopePriorityNode(const std::string & focusScopeId,const RefPtr<FocusHub> & priorFocusHub,bool pushFront)290 void FocusManager::AddScopePriorityNode(const std::string& focusScopeId, const RefPtr<FocusHub>& priorFocusHub,
291 bool pushFront)
292 {
293 auto iter = focusHubScopeMap_.find(focusScopeId);
294 if (iter != focusHubScopeMap_.end()) {
295 if (pushFront) {
296 iter->second.second.emplace_front(priorFocusHub);
297 } else {
298 iter->second.second.emplace_back(priorFocusHub);
299 }
300 } else {
301 focusHubScopeMap_[focusScopeId] = { nullptr, { priorFocusHub } };
302 }
303 }
304
RemoveScopePriorityNode(const std::string & focusScopeId,const RefPtr<FocusHub> & priorFocusHub)305 void FocusManager::RemoveScopePriorityNode(const std::string& focusScopeId, const RefPtr<FocusHub>& priorFocusHub)
306 {
307 auto iter = focusHubScopeMap_.find(focusScopeId);
308 if (iter != focusHubScopeMap_.end()) {
309 if (iter->second.second.empty()) {
310 return;
311 }
312 iter->second.second.remove(priorFocusHub);
313 auto focusScope = iter->second.first.Upgrade();
314 if (!focusScope && iter->second.second.empty()) {
315 focusHubScopeMap_.erase(iter);
316 }
317 }
318 }
319
GetFocusScopePriorityList(const std::string & focusScopeId)320 std::optional<std::list<WeakPtr<FocusHub>>*> FocusManager::GetFocusScopePriorityList(const std::string& focusScopeId)
321 {
322 auto iter = focusHubScopeMap_.find(focusScopeId);
323 if (iter != focusHubScopeMap_.end()) {
324 if (!iter->second.second.empty()) {
325 return &(iter->second.second);
326 }
327 }
328 return std::nullopt;
329 }
330
UpdateCurrentFocus(const RefPtr<FocusHub> & current,SwitchingUpdateReason reason)331 void FocusManager::UpdateCurrentFocus(const RefPtr<FocusHub>& current, SwitchingUpdateReason reason)
332 {
333 if (isSwitchingFocus_.value_or(false)) {
334 switchingFocus_ = current;
335 updateReason_ = reason;
336 }
337 }
338
GetCurrentFocus()339 RefPtr<FocusHub> FocusManager::GetCurrentFocus()
340 {
341 return currentFocus_.Upgrade();
342 }
343
TriggerAllFocusActiveChangeCallback(bool isFocusActive)344 void FocusManager::TriggerAllFocusActiveChangeCallback(bool isFocusActive)
345 {
346 auto focusActiveChangeCallbackManager = GetFocusActiveChangeCallbackManager();
347 if (focusActiveChangeCallbackManager) {
348 focusActiveChangeCallbackManager->NotifyListener(isFocusActive);
349 }
350 auto isFocusActiveUpdateEventManager = GetIsFocusActiveUpdateEventManager();
351 if (isFocusActiveUpdateEventManager) {
352 isFocusActiveUpdateEventManager->NotifyListener(isFocusActive);
353 }
354 }
355
GetFocusManager(RefPtr<FrameNode> & node)356 RefPtr<FocusManager> FocusManager::GetFocusManager(RefPtr<FrameNode>& node)
357 {
358 CHECK_NULL_RETURN(node, nullptr);
359 auto context = node->GetContextRefPtr();
360 CHECK_NULL_RETURN(context, nullptr);
361 auto focusManager = context->GetFocusManager();
362 return focusManager;
363 }
364
FocusSwitchingStart(const RefPtr<FocusHub> & focusHub,SwitchingStartReason reason)365 void FocusManager::FocusSwitchingStart(const RefPtr<FocusHub>& focusHub,
366 SwitchingStartReason reason)
367 {
368 isSwitchingFocus_ = true;
369 switchingFocus_ = focusHub;
370 startReason_ = reason;
371 }
372
ReportFocusSwitching(FocusReason focusReason)373 void FocusManager::ReportFocusSwitching(FocusReason focusReason)
374 {
375 auto callbacksManager = GetFocusChangeCallbackManager();
376 if (callbacksManager) {
377 callbacksManager->NotifyListener(currentFocus_, switchingFocus_, focusReason);
378 }
379 currentFocus_ = switchingFocus_;
380 isSwitchingFocus_.reset();
381 startReason_.reset();
382 updateReason_.reset();
383 endReason_.reset();
384 }
385
FocusSwitchingEnd(SwitchingEndReason reason)386 void FocusManager::FocusSwitchingEnd(SwitchingEndReason reason)
387 {
388 // While switching window, focus may move by steps.(WindowFocus/FlushFocus)
389 // Merge all steps together as a single movement.
390 if (!isSwitchingFocus_.value_or(false)) {
391 return;
392 }
393 if (!isSwitchingWindow_) {
394 auto lastHub = currentFocus_.Upgrade();
395 TAG_LOGI(AceLogTag::ACE_FOCUS, "FocusSwitch end, %{public}s/" SEC_PLD(%{public}d) " onBlur, "
396 "%{public}s/" SEC_PLD(%{public}d) " onFocus, "
397 "start: %{public}d, end: %{public}d, update: %{public}d",
398 lastHub ? lastHub->GetFrameName().c_str() : "NULL",
399 SEC_PARAM(lastHub ? lastHub->GetFrameId() : -1),
400 switchingFocus_ ? switchingFocus_->GetFrameName().c_str() : "NULL",
401 SEC_PARAM(switchingFocus_ ? switchingFocus_->GetFrameId() : -1),
402 startReason_.value_or(SwitchingStartReason::DEFAULT),
403 reason, updateReason_.value_or(SwitchingUpdateReason::DEFAULT));
404 if (switchingFocus_ &&
405 startReason_.value_or(SwitchingStartReason::DEFAULT) != SwitchingStartReason::LOST_FOCUS_TO_VIEW_ROOT) {
406 switchingFocus_->ClearLastFocusNode();
407 }
408 ReportFocusSwitching(FocusReason::DEFAULT);
409 PaintFocusState();
410 } else {
411 isSwitchingFocus_ = false;
412 endReason_ = reason;
413 }
414 }
415
WindowFocusMoveStart()416 void FocusManager::WindowFocusMoveStart()
417 {
418 isSwitchingWindow_ = true;
419 }
420
WindowFocusMoveEnd()421 void FocusManager::WindowFocusMoveEnd()
422 {
423 isSwitchingWindow_ = false;
424 if (!isSwitchingFocus_.value_or(true)) {
425 auto lastHub = currentFocus_.Upgrade();
426 TAG_LOGI(AceLogTag::ACE_FOCUS, "WinFocusMove end, %{public}s/" SEC_PLD(%{public}d) " onBlur, "
427 "%{public}s/" SEC_PLD(%{public}d) " onFocus, "
428 "start: %{public}d, end: %{public}d, update: %{public}d",
429 lastHub ? lastHub->GetFrameName().c_str() : "NULL",
430 SEC_PARAM(lastHub ? lastHub->GetFrameId() : -1),
431 switchingFocus_ ? switchingFocus_->GetFrameName().c_str() : "NULL",
432 SEC_PARAM(switchingFocus_ ? switchingFocus_->GetFrameId() : -1),
433 startReason_.value_or(SwitchingStartReason::DEFAULT),
434 endReason_.value_or(SwitchingEndReason::DEFAULT),
435 updateReason_.value_or(SwitchingUpdateReason::DEFAULT));
436 ReportFocusSwitching(FocusReason::WINDOW_FOCUS);
437 PaintFocusState();
438 }
439 }
440
CreateFocusGuard(const RefPtr<FocusHub> & focusHub,const RefPtr<FocusManager> & focusManager,SwitchingStartReason reason)441 void FocusManager::FocusGuard::CreateFocusGuard(const RefPtr<FocusHub>& focusHub,
442 const RefPtr<FocusManager>& focusManager, SwitchingStartReason reason)
443 {
444 CHECK_NULL_VOID(focusManager);
445 if (focusManager->isSwitchingFocus_.value_or(false)) {
446 return;
447 }
448 focusManager->FocusSwitchingStart(focusHub, reason);
449 focusMng_ = focusManager;
450 }
451
FocusGuard(const RefPtr<FocusHub> & focusHub,SwitchingStartReason reason)452 FocusManager::FocusGuard::FocusGuard(const RefPtr<FocusHub>& focusHub,
453 SwitchingStartReason reason)
454 {
455 RefPtr<FocusHub> hub = focusHub;
456 if (!hub || !hub->GetFocusManager()) {
457 auto curFocusView = FocusView::GetCurrentFocusView();
458 hub = curFocusView ? curFocusView->GetFocusHub() : nullptr;
459 }
460
461 auto mng = hub ? hub->GetFocusManager() : GetCurrentFocusManager();
462 CreateFocusGuard(hub, mng, reason);
463 }
464
~FocusGuard()465 FocusManager::FocusGuard::~FocusGuard()
466 {
467 if (focusMng_) {
468 focusMng_->FocusSwitchingEnd();
469 }
470 }
471
SetFocusViewRootScope(const RefPtr<FocusView> & focusView)472 bool FocusManager::SetFocusViewRootScope(const RefPtr<FocusView>& focusView)
473 {
474 auto focusViewRootScope = focusView->GetViewRootScope();
475 focusView->SetIsViewRootScopeFocused(true);
476 return focusViewRootScope->RequestFocusImmediatelyInner();
477 }
478
WindowFocus(bool isFocus)479 void FocusManager::WindowFocus(bool isFocus)
480 {
481 if (!isFocus) {
482 return;
483 }
484 WindowFocusMoveStart();
485 FocusManager::FocusGuard guard(GetCurrentFocus(), SwitchingStartReason::WINDOW_FOCUS);
486 auto curFocusView = GetLastFocusView().Upgrade();
487 auto curFocusViewHub = curFocusView ? curFocusView->GetFocusHub() : nullptr;
488 if (!curFocusViewHub) {
489 TAG_LOGW(AceLogTag::ACE_FOCUS, "Current focus view can not found!");
490 } else if (curFocusView->GetIsViewHasFocused() && !curFocusViewHub->IsCurrentFocus()) {
491 TAG_LOGD(AceLogTag::ACE_FOCUS, "Request current focus view: %{public}s/%{public}d",
492 curFocusView->GetFrameName().c_str(), curFocusView->GetFrameId());
493 if (!IsAutoFocusTransfer()) {
494 SetFocusViewRootScope(curFocusView);
495 } else {
496 auto lastViewFocusNode = curFocusViewHub->GetFocusLeaf();
497 lastViewFocusNode->RequestFocusImmediatelyInner(FocusReason::WINDOW_FOCUS);
498 }
499 } else {
500 auto container = Container::Current();
501 if (container && (container->IsUIExtensionWindow() || container->IsDynamicRender())) {
502 TAG_LOGD(AceLogTag::ACE_FOCUS,
503 "Request default focus on current focus view: %{public}s/%{public}d",
504 curFocusView->GetFrameName().c_str(),
505 curFocusView->GetFrameId());
506 curFocusView->SetIsViewRootScopeFocused(false);
507 curFocusView->RequestDefaultFocus();
508 }
509 }
510
511 auto pipeline = pipeline_.Upgrade();
512 CHECK_NULL_VOID(pipeline);
513 auto root = pipeline->GetRootElement();
514 CHECK_NULL_VOID(root);
515 auto rootFocusHub = root->GetFocusHub();
516 CHECK_NULL_VOID(rootFocusHub);
517 if (!rootFocusHub->IsCurrentFocus()) {
518 TAG_LOGD(AceLogTag::ACE_FOCUS,
519 "Request focus on rootFocusHub: %{public}s/%{public}d",
520 rootFocusHub->GetFrameName().c_str(),
521 rootFocusHub->GetFrameId());
522 auto focusDepend = rootFocusHub->GetFocusDependence();
523 rootFocusHub->SetFocusDependence(FocusDependence::SELF);
524 rootFocusHub->RequestFocusImmediatelyInner(FocusReason::WINDOW_FOCUS);
525 rootFocusHub->SetFocusDependence(focusDepend);
526 }
527 pipeline->RequestFrame();
528 }
529
SetIsFocusActive(bool isFocusActive,FocusActiveReason reason,bool autoFocusInactive)530 bool FocusManager::SetIsFocusActive(bool isFocusActive, FocusActiveReason reason, bool autoFocusInactive)
531 {
532 if (!NeedChangeFocusAvtive(isFocusActive, reason, autoFocusInactive)) {
533 return false;
534 }
535 TAG_LOGI(AceLogTag::ACE_FOCUS, "focusActive turns:%{public}d, reason:%{public}d", isFocusActive, reason);
536
537 SyncWindowsFocus(isFocusActive, reason, autoFocusInactive);
538 TriggerAllFocusActiveChangeCallback(isFocusActive);
539
540 auto pipeline = pipeline_.Upgrade();
541 CHECK_NULL_RETURN(pipeline, false);
542 auto rootNode = pipeline->GetRootElement();
543 CHECK_NULL_RETURN(rootNode, false);
544 auto rootFocusHub = rootNode->GetFocusHub();
545 CHECK_NULL_RETURN(rootFocusHub, false);
546 if (isFocusActive_) {
547 return rootFocusHub->PaintAllFocusState();
548 }
549 rootFocusHub->ClearAllFocusState();
550 return true;
551 }
552
SyncWindowsFocus(bool isFocusActive,FocusActiveReason reason,bool autoFocusInactive)553 bool FocusManager::SyncWindowsFocus(bool isFocusActive, FocusActiveReason reason, bool autoFocusInactive)
554 {
555 isFocusActive_ = isFocusActive;
556 auto pipeline = pipeline_.Upgrade();
557 CHECK_NULL_RETURN(pipeline, false);
558 auto containerId = Container::CurrentId();
559 auto container = Container::Current();
560 CHECK_NULL_RETURN(container, false);
561
562 auto isSubContainer = container->IsSubContainer();
563 if (!isSubContainer) {
564 auto subWindowContainerId = SubwindowManager::GetInstance()->GetSubContainerId(containerId);
565 if (subWindowContainerId >= 0) {
566 auto subPipeline = pipeline->GetContextByContainerId(subWindowContainerId);
567 CHECK_NULL_RETURN(subPipeline, false);
568 ContainerScope scope(subWindowContainerId);
569 auto subFocusManager = subPipeline->GetOrCreateFocusManager();
570 CHECK_NULL_RETURN(subFocusManager, false);
571 if (isFocusActive_ != subFocusManager->GetIsFocusActive()) {
572 subFocusManager->SetIsFocusActive(isFocusActive, reason, autoFocusInactive);
573 }
574 }
575 return true;
576 }
577 auto parentContainerId = Container::CurrentId();
578 if (parentContainerId >= 0) {
579 auto parentPipeline = pipeline->GetContextByContainerId(containerId);
580 CHECK_NULL_RETURN(parentPipeline, false);
581 ContainerScope scope(parentContainerId);
582 auto parentFocusManager = parentPipeline->GetOrCreateFocusManager();
583 CHECK_NULL_RETURN(parentFocusManager, false);
584 if (isFocusActive_ != parentFocusManager->GetIsFocusActive()) {
585 // To prevent recursive invocation between the parent and child windows.
586 parentFocusManager->SetIsFocusActive(isFocusActive, reason, autoFocusInactive);
587 }
588 }
589 return true;
590 }
591
NeedChangeFocusAvtive(bool isFocusActive,FocusActiveReason reason,bool autoFocusInactive)592 bool FocusManager::NeedChangeFocusAvtive(bool isFocusActive, FocusActiveReason reason, bool autoFocusInactive)
593 {
594 if (reason == FocusActiveReason::USE_API) {
595 TAG_LOGI(AceLogTag::ACE_FOCUS, "autoFocusInactive turns to %{public}d", autoFocusInactive);
596 autoFocusInactive_ = autoFocusInactive;
597 }
598 if (isFocusActive_ == isFocusActive) {
599 return false;
600 }
601 if (reason == FocusActiveReason::ACTIVE_MARK) {
602 return true;
603 }
604 if (isFocusActive) {
605 if (!SystemProperties::GetFocusCanBeActive()) {
606 TAG_LOGI(AceLogTag::ACE_FOCUS, "FocusActive false");
607 return false;
608 }
609 auto pipeline = pipeline_.Upgrade();
610 auto appTheme = pipeline ? pipeline->GetTheme<AppTheme>() : nullptr;
611 if (reason == FocusActiveReason::KEY_TAB && appTheme && !appTheme->NeedFocusActiveByTab()) {
612 return false;
613 }
614 }
615 if (!isFocusActive && reason == FocusActiveReason::POINTER_EVENT && !autoFocusInactive_) {
616 TAG_LOGI(AceLogTag::ACE_FOCUS, "focus cannot be deactived automaticly by pointer event");
617 return false;
618 }
619 return true;
620 }
621
HandleKeyForExtendOrActivateFocus(const KeyEvent & event,const RefPtr<FocusView> & curFocusView)622 bool FocusManager::HandleKeyForExtendOrActivateFocus(const KeyEvent& event, const RefPtr<FocusView>& curFocusView)
623 {
624 if (event.action == KeyAction::DOWN) {
625 if (event.activeMark.has_value()) {
626 if (event.activeMark.value()) {
627 return ExtendOrActivateFocus(curFocusView, FocusActiveReason::ACTIVE_MARK);
628 } else {
629 return SetIsFocusActive(false, FocusActiveReason::ACTIVE_MARK);
630 }
631 }
632 if (event.IsKey({ KeyCode::KEY_TAB })) {
633 return ExtendOrActivateFocus(curFocusView, FocusActiveReason::KEY_TAB);
634 }
635 if (event.IsDirectionalKey() && event.sourceType == SourceType::JOYSTICK) {
636 return ExtendOrActivateFocus(curFocusView, FocusActiveReason::JOYSTICK_DPAD);
637 }
638 auto curEntryFocusView = curFocusView ? curFocusView->GetEntryFocusView() : nullptr;
639 auto curEntryFocusHub = curEntryFocusView ? curFocusView->GetFocusHub() : nullptr;
640 if (event.IsDirectionalKey() && curEntryFocusHub && curEntryFocusHub->GetDirectionalKeyFocus()) {
641 return ExtendOrActivateFocus(curFocusView);
642 }
643 }
644 return false;
645 }
646
ExtendOrActivateFocus(const RefPtr<FocusView> & curFocusView,FocusActiveReason reason)647 bool FocusManager::ExtendOrActivateFocus(const RefPtr<FocusView>& curFocusView, FocusActiveReason reason)
648 {
649 auto isViewRootScopeFocused = curFocusView ? curFocusView->GetIsViewRootScopeFocused() : true;
650 auto isExtend = false;
651 if (curFocusView && isViewRootScopeFocused) {
652 isExtend = curFocusView->TriggerFocusMove();
653 }
654 auto isActive = SetIsFocusActive(true, reason);
655 return isExtend || isActive;
656 }
657 } // namespace OHOS::Ace::NG
658