• 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_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