• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2023 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 "window_node_container.h"
17 
18 #include <ability_manager_client.h>
19 #include <algorithm>
20 #include <cinttypes>
21 #include <cmath>
22 #include <ctime>
23 #include <display_power_mgr_client.h>
24 #include <hitrace_meter.h>
25 #include <limits>
26 #include <power_mgr_client.h>
27 #include <transaction/rs_interfaces.h>
28 #include <transaction/rs_transaction.h>
29 #include <transaction/rs_sync_transaction_controller.h>
30 
31 #include "common_event_manager.h"
32 #include "dm_common.h"
33 #include "remote_animation.h"
34 #include "starting_window.h"
35 #include "window_helper.h"
36 #include "window_inner_manager.h"
37 #include "window_layout_policy_cascade.h"
38 #include "window_layout_policy_tile.h"
39 #include "window_manager_agent_controller.h"
40 #include "window_manager_hilog.h"
41 #include "window_manager_service.h"
42 #include "window_manager_service_utils.h"
43 #include "window_system_effect.h"
44 #include "wm_common.h"
45 #include "wm_common_inner.h"
46 
47 namespace OHOS {
48 namespace Rosen {
49 namespace {
50     constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "Container"};
51     constexpr int WINDOW_NAME_MAX_LENGTH = 10;
52     constexpr uint32_t MAX_BRIGHTNESS = 255;
53     constexpr uint32_t SPLIT_WINDOWS_CNT = 2;
54     constexpr uint32_t EXIT_SPLIT_POINTS_NUMBER = 2;
55     constexpr int UID_TRANSFROM_DIVISOR = 200000;
56     constexpr int UID_MIN = 100;
57 }
58 AnimationConfig WindowNodeContainer::animationConfig_;
59 bool WindowNodeContainer::isFloatWindowAboveFullWindow_ = false;
60 uint32_t WindowNodeContainer::maxMainFloatingWindowNumber_ = 100;
61 bool WindowNodeContainer::isAnimateTransactionEnabled_ = false;
62 
WindowNodeContainer(const sptr<DisplayInfo> & displayInfo,ScreenId displayGroupId)63 WindowNodeContainer::WindowNodeContainer(const sptr<DisplayInfo>& displayInfo, ScreenId displayGroupId)
64 {
65     DisplayId displayId = displayInfo->GetDisplayId();
66 
67     // create and displayGroupInfo and displayGroupController
68     DisplayGroupInfo::GetInstance().Init(displayGroupId, displayInfo);
69     displayGroupController_ = new DisplayGroupController(this);
70     displayGroupController_->InitNewDisplay(displayId);
71 
72     // init layout policy
73     layoutPolicies_[WindowLayoutMode::CASCADE] = new WindowLayoutPolicyCascade(
74             displayGroupController_->displayGroupWindowTree_);
75     layoutPolicies_[WindowLayoutMode::TILE] = new WindowLayoutPolicyTile(
76         displayGroupController_->displayGroupWindowTree_);
77     layoutPolicy_ = layoutPolicies_[WindowLayoutMode::CASCADE];
78     layoutPolicy_->Launch();
79 
80     // set initial divider rect in windowPair
81     Rect initialDivRect = layoutPolicies_[WindowLayoutMode::CASCADE]->GetDividerRect(displayId);
82     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId);
83     if (windowPair != nullptr) {
84         windowPair->SetDividerRect(initialDivRect);
85     }
86 
87     // init avoidAreaController
88     avoidController_ = new AvoidAreaController(focusedWindow_);
89     WindowInnerManager::GetInstance().NotifyDisplayLimitRectChange(
90         DisplayGroupInfo::GetInstance().GetAllDisplayRects());
91     isAnimateTransactionEnabled_ = system::GetParameter("persist.window.animateTransaction.enabled", "1")  == "1";
92 }
93 
~WindowNodeContainer()94 WindowNodeContainer::~WindowNodeContainer()
95 {
96     Destroy();
97 }
98 
GetWindowCountByType(WindowType windowType)99 uint32_t WindowNodeContainer::GetWindowCountByType(WindowType windowType)
100 {
101     uint32_t windowNumber = 0;
102     auto counter = [&windowNumber, &windowType](sptr<WindowNode>& windowNode) {
103         if (windowNode->GetWindowType() == windowType && !windowNode->startingWindowShown_) {
104             ++windowNumber;
105         }
106     };
107     std::for_each(belowAppWindowNode_->children_.begin(), belowAppWindowNode_->children_.end(), counter);
108     std::for_each(appWindowNode_->children_.begin(), appWindowNode_->children_.end(), counter);
109     std::for_each(aboveAppWindowNode_->children_.begin(), aboveAppWindowNode_->children_.end(), counter);
110     return windowNumber;
111 }
112 
GetMainFloatingWindowCount()113 uint32_t WindowNodeContainer::GetMainFloatingWindowCount()
114 {
115     uint32_t windowNumber = 0;
116     auto counter = [&windowNumber](sptr<WindowNode>& windowNode) {
117         WindowType windowType = windowNode->GetWindowType();
118         WindowMode windowMode = windowNode->GetWindowMode();
119         if (WindowHelper::IsMainFloatingWindow(windowType, windowMode) &&
120             !windowNode->startingWindowShown_) {
121             ++windowNumber;
122         }
123     };
124     std::for_each(appWindowNode_->children_.begin(), appWindowNode_->children_.end(), counter);
125     std::for_each(aboveAppWindowNode_->children_.begin(), aboveAppWindowNode_->children_.end(), counter);
126     return windowNumber;
127 }
128 
AddWindowNodeOnWindowTree(sptr<WindowNode> & node,const sptr<WindowNode> & parentNode)129 WMError WindowNodeContainer::AddWindowNodeOnWindowTree(sptr<WindowNode>& node, const sptr<WindowNode>& parentNode)
130 {
131     sptr<WindowNode> root = FindRoot(node->GetWindowType());
132     if (root == nullptr && !(WindowHelper::IsSystemSubWindow(node->GetWindowType()) &&
133         parentNode != nullptr)) {
134         WLOGFE("root is nullptr!");
135         return WMError::WM_ERROR_NULLPTR;
136     }
137     node->requestedVisibility_ = true;
138     if (parentNode != nullptr) { // subwindow
139         if (WindowHelper::IsSystemSubWindow(node->GetWindowType()) ||
140             node->GetWindowType() == WindowType::WINDOW_TYPE_APP_COMPONENT) {
141             if (WindowHelper::IsSubWindow(parentNode->GetWindowType()) ||
142                 WindowHelper::IsSystemSubWindow(parentNode->GetWindowType()) ||
143                 parentNode->GetWindowType() == WindowType::WINDOW_TYPE_APP_COMPONENT ||
144                 parentNode->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG) {
145                 // some times, dialog is a child window, so exclude
146                 WLOGFE("the parent of window cannot be any sub window");
147                 return WMError::WM_ERROR_INVALID_PARAM;
148             }
149         } else {
150             if (parentNode->parent_ != root &&
151                 !((parentNode->GetWindowFlags() & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)) &&
152                 (parentNode->parent_ == aboveAppWindowNode_))) {
153                 WLOGFE("window type and parent window not match \
154                     or try to add subwindow to subwindow, which is forbidden");
155                 return WMError::WM_ERROR_INVALID_PARAM;
156             }
157         }
158         node->currentVisibility_ = parentNode->currentVisibility_;
159         node->parent_ = parentNode;
160     } else { // mainwindow
161         node->parent_ = root;
162         node->currentVisibility_ = true;
163         for (auto& child : node->children_) {
164             child->currentVisibility_ = child->requestedVisibility_;
165         }
166         if (WindowHelper::IsSystemBarWindow(node->GetWindowType())) {
167             displayGroupController_->sysBarNodeMaps_[node->GetDisplayId()][node->GetWindowType()] = node;
168         }
169     }
170     return WMError::WM_OK;
171 }
172 
ShowStartingWindow(sptr<WindowNode> & node)173 WMError WindowNodeContainer::ShowStartingWindow(sptr<WindowNode>& node)
174 {
175     if (node->currentVisibility_) {
176         WLOGFE("current window is visible, windowId: %{public}u", node->GetWindowId());
177         return WMError::WM_ERROR_INVALID_OPERATION;
178     }
179 
180     WMError res = AddWindowNodeOnWindowTree(node, nullptr);
181     if (res != WMError::WM_OK) {
182         return res;
183     }
184     UpdateWindowTree(node);
185     displayGroupController_->PreProcessWindowNode(node, WindowUpdateType::WINDOW_UPDATE_ADDED);
186     StartingWindow::AddNodeOnRSTree(node, layoutPolicy_->IsMultiDisplay());
187     AssignZOrder();
188     layoutPolicy_->PerformWindowLayout(node, WindowUpdateType::WINDOW_UPDATE_ADDED);
189     WLOGI("ShowStartingWindow windowId: %{public}u end", node->GetWindowId());
190     return WMError::WM_OK;
191 }
192 
IsTileRectSatisfiedWithSizeLimits(sptr<WindowNode> & node)193 WMError WindowNodeContainer::IsTileRectSatisfiedWithSizeLimits(sptr<WindowNode>& node)
194 {
195     if (layoutMode_ == WindowLayoutMode::TILE &&
196         !layoutPolicy_->IsTileRectSatisfiedWithSizeLimits(node)) {
197         WLOGFE("layoutMode is tile, default rect is not satisfied with size limits of window, windowId: %{public}u",
198             node->GetWindowId());
199         return WMError::WM_ERROR_INVALID_WINDOW_MODE_OR_SIZE;
200     }
201     return WMError::WM_OK;
202 }
203 
GetAnimationConfigRef()204 AnimationConfig& WindowNodeContainer::GetAnimationConfigRef()
205 {
206     return animationConfig_;
207 }
208 
LayoutWhenAddWindowNode(sptr<WindowNode> & node,bool afterAnimation)209 void WindowNodeContainer::LayoutWhenAddWindowNode(sptr<WindowNode>& node, bool afterAnimation)
210 {
211     if (afterAnimation) {
212         layoutPolicy_->PerformWindowLayout(node, WindowUpdateType::WINDOW_UPDATE_ADDED);
213         return;
214     }
215     WLOGFD("AddWindowNode Id:%{public}u, currState:%{public}u",
216         node->GetWindowId(), static_cast<uint32_t>(node->stateMachine_.GetCurrentState()));
217     if (WindowHelper::IsMainWindow(node->GetWindowType()) &&
218         RemoteAnimation::IsRemoteAnimationEnabledAndFirst(node->GetDisplayId()) &&
219         node->stateMachine_.IsShowAnimationPlaying()) {
220         // for first frame callback
221         auto winRect = node->GetWindowRect();
222         if (node->surfaceNode_) {
223             node->surfaceNode_->SetBounds(0, 0, winRect.width_, winRect.height_);
224             WLOGI("SetBounds id:%{public}u, rect:[%{public}d, %{public}d, %{public}u, %{public}u]",
225                 node->GetWindowId(), winRect.posX_, winRect.posY_, winRect.width_, winRect.height_);
226             layoutPolicy_->NotifyClientAndAnimation(node, winRect, WindowSizeChangeReason::UNDEFINED);
227         }
228     } else {
229         if (node->GetWindowProperty()->GetAnimationFlag() == static_cast<uint32_t>(WindowAnimation::CUSTOM) &&
230             WindowHelper::IsSystemWindow(node->GetWindowType())) {
231                 node->SetWindowSizeChangeReason(WindowSizeChangeReason::CUSTOM_ANIMATION_SHOW);
232         }
233         layoutPolicy_->PerformWindowLayout(node, WindowUpdateType::WINDOW_UPDATE_ADDED);
234     }
235 }
236 
AddWindowNode(sptr<WindowNode> & node,sptr<WindowNode> & parentNode,bool afterAnimation)237 WMError WindowNodeContainer::AddWindowNode(sptr<WindowNode>& node, sptr<WindowNode>& parentNode, bool afterAnimation)
238 {
239     if (!node->startingWindowShown_) { // window except main Window
240         WMError res = AddWindowNodeOnWindowTree(node, parentNode);
241         if (res != WMError::WM_OK) {
242             return res;
243         }
244         UpdateWindowTree(node);
245         displayGroupController_->PreProcessWindowNode(node, WindowUpdateType::WINDOW_UPDATE_ADDED);
246         // add node on RSTree
247         for (auto& displayId : node->GetShowingDisplays()) {
248             AddNodeOnRSTree(node, displayId, displayId, WindowUpdateType::WINDOW_UPDATE_ADDED,
249                 node->isPlayAnimationShow_);
250         }
251     } else { // only main app window has starting window
252         node->isPlayAnimationShow_ = false;
253         node->startingWindowShown_ = false;
254         AddAppSurfaceNodeOnRSTree(node);
255         ReZOrderShowWhenLockedWindowIfNeeded(node);
256         RaiseZOrderForAppWindow(node, parentNode);
257     }
258     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(node->GetDisplayId());
259     if (windowPair == nullptr) {
260         WLOGFE("Window pair is nullptr");
261         return WMError::WM_ERROR_NULLPTR;
262     }
263     windowPair->UpdateIfSplitRelated(node);
264     if (node->IsSplitMode()) {
265         // raise the z-order of window pair
266         RaiseSplitRelatedWindowToTop(node);
267         if (isFloatWindowAboveFullWindow_ && !windowPair->IsDuringSplit()) {
268             ResetAllMainFloatingWindowZOrder(appWindowNode_);
269         }
270     }
271     MinimizeOldestMainFloatingWindow(node->GetWindowId());
272     AssignZOrder();
273     LayoutWhenAddWindowNode(node, afterAnimation);
274     NotifyIfAvoidAreaChanged(node, AvoidControlType::AVOID_NODE_ADD);
275     DumpScreenWindowTreeByWinId(node->GetWindowId());
276     UpdateCameraFloatWindowStatus(node, true);
277     if (WindowHelper::IsMainWindow(node->GetWindowType())) {
278         backupWindowIds_.clear();
279     }
280 
281     if (node->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD) {
282         isScreenLocked_ = true;
283         SetBelowScreenlockVisible(node, false);
284     }
285     if (node->GetWindowType() == WindowType::WINDOW_TYPE_WALLPAPER) {
286         RemoteAnimation::NotifyAnimationUpdateWallpaper(node);
287     }
288     WLOGI("AddWindowNode Id: %{public}u end", node->GetWindowId());
289     RSInterfaces::GetInstance().SetAppWindowNum(GetAppWindowNum());
290     // update private window count and notify dms private status changed
291     if (node->GetWindowProperty()->GetPrivacyMode() && !node->GetWindowProperty()->GetOnlySkipSnapshot()) {
292         UpdatePrivateStateAndNotify();
293     }
294     if (WindowHelper::IsMainWindow(node->GetWindowType())) {
295         WindowInfoReporter::GetInstance().InsertShowReportInfo(node->abilityInfo_.bundleName_);
296     }
297     return WMError::WM_OK;
298 }
299 
UpdateRSTreeWhenShowingDisplaysChange(sptr<WindowNode> & node,const std::vector<DisplayId> & lastShowingDisplays)300 void WindowNodeContainer::UpdateRSTreeWhenShowingDisplaysChange(sptr<WindowNode>& node,
301     const std::vector<DisplayId>& lastShowingDisplays)
302 {
303     if (!layoutPolicy_->IsMultiDisplay()) {
304         return;
305     }
306 
307     // Update RSTree
308     auto curShowingDisplays = node->GetShowingDisplays();
309     for (auto& displayId : lastShowingDisplays) {
310         if (std::find(curShowingDisplays.begin(), curShowingDisplays.end(), displayId) == curShowingDisplays.end()) {
311             RemoveNodeFromRSTree(node, displayId, *(curShowingDisplays.begin()),
312                 WindowUpdateType::WINDOW_UPDATE_ACTIVE);
313             WLOGI("remove from RSTree : %{public}" PRIu64"", displayId);
314         }
315     }
316 
317     for (auto& displayId : curShowingDisplays) {
318         if (std::find(lastShowingDisplays.begin(), lastShowingDisplays.end(), displayId) == lastShowingDisplays.end()) {
319             AddNodeOnRSTree(node, displayId, displayId, WindowUpdateType::WINDOW_UPDATE_ACTIVE);
320             WLOGI("add on RSTree : %{public}" PRIu64"", displayId);
321         }
322     }
323 }
324 
UpdateWindowNode(sptr<WindowNode> & node,WindowUpdateReason reason)325 WMError WindowNodeContainer::UpdateWindowNode(sptr<WindowNode>& node, WindowUpdateReason reason)
326 {
327     // Get last displayId and last showing displays before layout
328     auto lastShowingDisplays = node->GetShowingDisplays();
329 
330     // PreProcess window node and layout node
331     displayGroupController_->PreProcessWindowNode(node, WindowUpdateType::WINDOW_UPDATE_ACTIVE);
332     if (WindowHelper::IsMainWindow(node->GetWindowType()) && WindowHelper::IsSwitchCascadeReason(reason)) {
333         SwitchLayoutPolicy(WindowLayoutMode::CASCADE, node->GetDisplayId());
334     }
335     layoutPolicy_->PerformWindowLayout(node, WindowUpdateType::WINDOW_UPDATE_ACTIVE);
336     displayGroupController_->PostProcessWindowNode(node);
337     // Get current displayId and showing displays, update RSTree and displayGroupWindowTree
338     UpdateRSTreeWhenShowingDisplaysChange(node, lastShowingDisplays);
339     NotifyIfAvoidAreaChanged(node, AvoidControlType::AVOID_NODE_UPDATE);
340     WLOGD("UpdateNode Id: %{public}u end", node->GetWindowId());
341     return WMError::WM_OK;
342 }
343 
RemoveWindowNodeFromWindowTree(sptr<WindowNode> & node)344 void WindowNodeContainer::RemoveWindowNodeFromWindowTree(sptr<WindowNode>& node)
345 {
346     // remove this node from parent
347     auto iter = std::find(node->parent_->children_.begin(), node->parent_->children_.end(), node);
348     if (iter != node->parent_->children_.end()) {
349         node->parent_->children_.erase(iter);
350     } else {
351         WLOGFE("can't find this node in parent");
352     }
353     node->parent_ = nullptr;
354 }
355 
RemoveFromRsTreeWhenRemoveWindowNode(sptr<WindowNode> & node,bool fromAnimation)356 void WindowNodeContainer::RemoveFromRsTreeWhenRemoveWindowNode(sptr<WindowNode>& node, bool fromAnimation)
357 {
358     if (fromAnimation || (RemoteAnimation::IsRemoteAnimationEnabledAndFirst(node->GetDisplayId()) &&
359         node->stateMachine_.IsHideAnimationPlaying())) {
360             WLOGFD("not remove from rs tree id:%{public}u", node->GetWindowId());
361             return;
362     }
363     // When RemoteAnimation exists, remove node from rs tree after animation
364     WLOGFD("Id:%{public}u, isPlayAnimationHide_:%{public}u", node->GetWindowId(),
365         static_cast<uint32_t>(node->isPlayAnimationHide_));
366     // subwindow or no remote animation also exit with animation
367     for (auto& displayId : node->GetShowingDisplays()) {
368         RemoveNodeFromRSTree(node, displayId, displayId, WindowUpdateType::WINDOW_UPDATE_REMOVED,
369             node->isPlayAnimationHide_);
370     }
371 }
372 
SetSurfaceNodeVisible(sptr<WindowNode> & node,int32_t topPriority,bool visible)373 void WindowNodeContainer::SetSurfaceNodeVisible(sptr<WindowNode>& node, int32_t topPriority, bool visible)
374 {
375     if (node == nullptr) {
376         return;
377     }
378     if (node->parent_ != nullptr && node->currentVisibility_) {
379         if (node->priority_ < topPriority && !WindowHelper::IsShowWhenLocked(node->GetWindowFlags()) &&
380             !WindowHelper::IsShowWhenLocked(node->parent_->GetWindowFlags())) {
381             auto surfaceNode = node->leashWinSurfaceNode_ != nullptr ? node->leashWinSurfaceNode_ : node->surfaceNode_;
382             if (surfaceNode) {
383                 surfaceNode->SetVisible(visible);
384             }
385         }
386     }
387     for (auto& childNode : node->children_) {
388         SetSurfaceNodeVisible(childNode, topPriority, visible);
389     }
390 }
391 
SetBelowScreenlockVisible(sptr<WindowNode> & node,bool visible)392 void WindowNodeContainer::SetBelowScreenlockVisible(sptr<WindowNode>& node, bool visible)
393 {
394     int32_t topPriority = zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_KEYGUARD);
395     std::vector<sptr<WindowNode>> rootNodes = { belowAppWindowNode_, appWindowNode_, aboveAppWindowNode_ };
396     for (auto& node : rootNodes) {
397         SetSurfaceNodeVisible(node, topPriority, visible);
398     }
399 }
400 
RemoveWindowNode(sptr<WindowNode> & node,bool fromAnimation)401 WMError WindowNodeContainer::RemoveWindowNode(sptr<WindowNode>& node, bool fromAnimation)
402 {
403     if (node == nullptr) {
404         WLOGFE("window node or surface node is nullptr, invalid");
405         return WMError::WM_ERROR_DESTROYED_OBJECT;
406     }
407     if (node->parent_ == nullptr) {
408         WLOGFW("can't find parent of this node");
409     } else {
410         RemoveWindowNodeFromWindowTree(node);
411     }
412 
413     node->requestedVisibility_ = false;
414     node->currentVisibility_ = false;
415     RemoveFromRsTreeWhenRemoveWindowNode(node, fromAnimation);
416     node->isPlayAnimationHide_ = false;
417     displayGroupController_->UpdateDisplayGroupWindowTree();
418     layoutPolicy_->PerformWindowLayout(node, WindowUpdateType::WINDOW_UPDATE_REMOVED);
419     WindowMode lastMode = node->GetWindowMode();
420     if (HandleRemoveWindow(node) != WMError::WM_OK) {
421         return WMError::WM_ERROR_NULLPTR;
422     }
423     if (!WindowHelper::IsFloatingWindow(lastMode)) {
424         NotifyDockWindowStateChanged(node, true);
425     }
426     NotifyIfAvoidAreaChanged(node, AvoidControlType::AVOID_NODE_REMOVE);
427     DumpScreenWindowTreeByWinId(node->GetWindowId());
428     UpdateCameraFloatWindowStatus(node, false);
429     if (node->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD) {
430         isScreenLocked_ = false;
431         SetBelowScreenlockVisible(node, true);
432     }
433     if (node->GetWindowType() == WindowType::WINDOW_TYPE_BOOT_ANIMATION) {
434         DisplayManagerServiceInner::GetInstance().SetGravitySensorSubscriptionEnabled();
435     }
436     WLOGI("Remove Id: %{public}u end", node->GetWindowId());
437     RSInterfaces::GetInstance().SetAppWindowNum(GetAppWindowNum());
438 
439     // update private window count and notify dms private status changed
440     if (node->GetWindowProperty()->GetPrivacyMode() && !node->GetWindowProperty()->GetOnlySkipSnapshot()) {
441         UpdatePrivateStateAndNotify();
442     }
443     if (WindowHelper::IsMainWindow(node->GetWindowType())) {
444         WindowInfoReporter::GetInstance().InsertHideReportInfo(node->abilityInfo_.bundleName_);
445     }
446     HandleRemoveWindowDisplayOrientation(node, fromAnimation);
447     return WMError::WM_OK;
448 }
449 
HandleRemoveWindowDisplayOrientation(sptr<WindowNode> & node,bool fromAnimation)450 void WindowNodeContainer::HandleRemoveWindowDisplayOrientation(sptr<WindowNode>& node, bool fromAnimation)
451 {
452     if (node->GetWindowMode() != WindowMode::WINDOW_MODE_FULLSCREEN) {
453         WLOGFD("[FixOrientation] not full screen window remove, do not update orientation");
454         return;
455     }
456     if (!FIX_ORIENTATION_ENABLE) {
457         auto nextRotatableWindow = GetNextRotatableWindow(node->GetWindowId());
458         if (nextRotatableWindow != nullptr) {
459             SetDisplayOrientationFromWindow(nextRotatableWindow, true);
460         }
461         return;
462     }
463     if (!fromAnimation) {
464         if (node->stateMachine_.IsHideAnimationPlaying()) {
465             WLOGFD("[FixOrientation] removing window is playing hide animation, do not update display orientation");
466             return;
467         }
468         auto nextRotatableWindow = GetNextRotatableWindow(node->GetWindowId());
469         if (nextRotatableWindow == nullptr) {
470             WLOGFD("[FixOrientation] no next window, do not update display orientation");
471             return;
472         }
473         WLOGFD("[FixOrientation] nexi rotatable window: %{public}u", nextRotatableWindow->GetWindowId());
474         if (nextRotatableWindow->stateMachine_.IsShowAnimationPlaying()) {
475             WLOGFD("[FixOrientation] next window is playing show animation, do not update display orientation");
476             return;
477         }
478         if (WmsUtils::IsFixedOrientation(nextRotatableWindow->GetRequestedOrientation(),
479             nextRotatableWindow->GetWindowMode(), nextRotatableWindow->GetWindowFlags())) {
480             WLOGFI("[FixOrientation] next rotatable window is fixed, do not animation");
481             SetDisplayOrientationFromWindow(nextRotatableWindow, false);
482         } else {
483             SetDisplayOrientationFromWindow(nextRotatableWindow, true);
484         }
485     }
486 }
487 
SetDisplayOrientationFromWindow(sptr<WindowNode> & node,bool withAnimation)488 void WindowNodeContainer::SetDisplayOrientationFromWindow(sptr<WindowNode>& node, bool withAnimation)
489 {
490     DisplayManagerServiceInner::GetInstance().SetOrientationFromWindow(node->GetDisplayId(),
491         node->GetRequestedOrientation(), withAnimation);
492 }
493 
UpdatePrivateStateAndNotify()494 void WindowNodeContainer::UpdatePrivateStateAndNotify()
495 {
496     uint32_t prePrivateWindowCount = privateWindowCount_;
497     WLOGFD("before update : privateWindow count: %{public}u", prePrivateWindowCount);
498     UpdatePrivateWindowCount();
499     if (prePrivateWindowCount == 0 && privateWindowCount_ == 1) {
500         DisplayManagerServiceInner::GetInstance().NotifyPrivateWindowStateChanged(true);
501     } else if (prePrivateWindowCount == 1 && privateWindowCount_ == 0) {
502         DisplayManagerServiceInner::GetInstance().NotifyPrivateWindowStateChanged(false);
503     }
504 }
505 
UpdatePrivateWindowCount()506 void WindowNodeContainer::UpdatePrivateWindowCount()
507 {
508     std::vector<sptr<WindowNode>> windowNodes;
509     TraverseContainer(windowNodes);
510     uint32_t count = 0;
511     for (const auto& node : windowNodes) {
512         if (node->GetWindowProperty()->GetPrivacyMode() && !node->GetWindowProperty()->GetOnlySkipSnapshot()) {
513             ++count;
514         }
515     }
516     privateWindowCount_ = count;
517     WLOGFD("after update : privateWindow count: %{public}u", privateWindowCount_);
518 }
519 
GetAppWindowNum()520 uint32_t WindowNodeContainer::GetAppWindowNum()
521 {
522     uint32_t num = 0;
523     for (auto& child : appWindowNode_->children_) {
524         if (WindowHelper::IsAppWindow(child->GetWindowType())) {
525             num++;
526         }
527     }
528     return num;
529 }
530 
SetConfigMainFloatingWindowAbove(bool isAbove)531 void WindowNodeContainer::SetConfigMainFloatingWindowAbove(bool isAbove)
532 {
533     isFloatWindowAboveFullWindow_ = isAbove;
534 }
535 
SetMaxMainFloatingWindowNumber(uint32_t maxNumber)536 void WindowNodeContainer::SetMaxMainFloatingWindowNumber(uint32_t maxNumber)
537 {
538     maxMainFloatingWindowNumber_ = maxNumber;
539 }
540 
ResetMainFloatingWindowPriorityIfNeeded(sptr<WindowNode> & windowNode)541 void WindowNodeContainer::ResetMainFloatingWindowPriorityIfNeeded(sptr<WindowNode>& windowNode)
542 {
543     if (!isFloatWindowAboveFullWindow_) {
544         return;
545     }
546     const WindowType& windowType = windowNode->GetWindowType();
547     const WindowMode& windowMode = windowNode->GetWindowMode();
548     if (!WindowHelper::IsMainFloatingWindow(windowType, windowMode)) {
549         return;
550     }
551     const int32_t priorityOffset = 1;
552     auto baseZOrderPolicy = zorderPolicy_->GetWindowPriority(windowType);
553     if (isScreenLocked_ &&
554         (windowNode->GetWindowFlags() & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED))) {
555         // if window show when lock, priority should bigger than KEYGUARD.
556         baseZOrderPolicy = zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_KEYGUARD) + 1;
557     }
558 
559     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(windowNode->GetDisplayId());
560     if (windowPair != nullptr && windowPair->IsDuringSplit()) {
561         windowNode->priority_ = baseZOrderPolicy - priorityOffset;
562         WLOGFD("Reset floating main window zorder priority.[windowId: %{public}u, priority: %{public}d] ",
563             windowNode->GetWindowId(), windowNode->priority_);
564         return;
565     }
566 
567     windowNode->priority_ = baseZOrderPolicy + priorityOffset;
568     WLOGFD("Reset floating main window zorder priority.[windowId: %{public}u, priority: %{public}d] ",
569         windowNode->GetWindowId(), windowNode->priority_);
570 }
571 
ResetAllMainFloatingWindowZOrder(sptr<WindowNode> & rootNode)572 void WindowNodeContainer::ResetAllMainFloatingWindowZOrder(sptr<WindowNode>& rootNode)
573 {
574     if (!isFloatWindowAboveFullWindow_) {
575         WLOGFD("The free window level above full screen window feature is turned off");
576         return;
577     }
578     if (rootNode != appWindowNode_ && rootNode != aboveAppWindowNode_) {
579         return;
580     }
581     /*
582      * update all mainFloatingWindow position on window tree with
583      * the same raleative position between mainFloatingWindows.
584      */
585     std::vector<sptr<WindowNode>> tempWindows;
586     auto itor = rootNode->children_.begin();
587     while (itor != rootNode->children_.end()) {
588         const WindowType& windowType = (*itor)->GetWindowType();
589         const WindowMode& windowMode = (*itor)->GetWindowMode();
590         if (WindowHelper::IsMainFloatingWindow(windowType, windowMode)) {
591             tempWindows.push_back(*itor);
592             itor = rootNode->children_.erase(itor);
593         } else {
594             itor++;
595         }
596     }
597 
598     for (auto& node : tempWindows) {
599         UpdateWindowTree(node);
600     }
601 }
602 
HandleRemoveWindow(sptr<WindowNode> & node)603 WMError WindowNodeContainer::HandleRemoveWindow(sptr<WindowNode>& node)
604 {
605     WLOGFD("start");
606     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(node->GetDisplayId());
607     if (windowPair == nullptr) {
608         WLOGFE("Window pair is nullptr");
609         return WMError::WM_ERROR_NULLPTR;
610     }
611     windowPair->HandleRemoveWindow(node);
612     auto dividerWindow = windowPair->GetDividerWindow();
613     auto type = node->GetWindowType();
614     if ((type == WindowType::WINDOW_TYPE_STATUS_BAR || type == WindowType::WINDOW_TYPE_NAVIGATION_BAR) &&
615         dividerWindow != nullptr) {
616         UpdateWindowNode(dividerWindow, WindowUpdateReason::UPDATE_RECT);
617     }
618     WLOGFD("end");
619     return WMError::WM_OK;
620 }
621 
DestroyWindowNode(sptr<WindowNode> & node,std::vector<uint32_t> & windowIds)622 WMError WindowNodeContainer::DestroyWindowNode(sptr<WindowNode>& node, std::vector<uint32_t>& windowIds)
623 {
624     WMError ret = RemoveWindowNode(node);
625     if (ret != WMError::WM_OK) {
626         WLOGFE("RemoveWindowNode failed");
627         return ret;
628     }
629     StartingWindow::ReleaseStartWinSurfaceNode(node);
630     node->surfaceNode_ = nullptr;
631     windowIds.push_back(node->GetWindowId());
632     for (auto& child : node->children_) { // destroy sub window if exists
633         windowIds.push_back(child->GetWindowId());
634         child->parent_ = nullptr;
635         if (child->surfaceNode_ != nullptr) {
636             WLOGI("child surfaceNode set nullptr");
637             child->surfaceNode_ = nullptr;
638         }
639     }
640 
641     // clear vector cache completely, swap with empty vector
642     auto emptyVector = std::vector<sptr<WindowNode>>();
643     node->children_.swap(emptyVector);
644     if (node->GetWindowType() == WindowType::WINDOW_TYPE_WALLPAPER) {
645         RemoteAnimation::NotifyAnimationUpdateWallpaper(nullptr);
646     }
647     if (WindowHelper::IsMainWindow(node->GetWindowType())) {
648         WindowInfoReporter::GetInstance().InsertDestroyReportInfo(node->abilityInfo_.bundleName_);
649     }
650 
651     UpdateAvoidAreaListener(node, false);
652     WLOGI("DestroyNode Id: %{public}u end", node->GetWindowId());
653     return WMError::WM_OK;
654 }
655 
UpdateSizeChangeReason(sptr<WindowNode> & node,WindowSizeChangeReason reason)656 void WindowNodeContainer::UpdateSizeChangeReason(sptr<WindowNode>& node, WindowSizeChangeReason reason)
657 {
658     if (!node->GetWindowToken()) {
659         WLOGFE("windowToken is null");
660         return;
661     }
662     if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
663         for (auto& child : appWindowNode_->children_) {
664             if (child->IsSplitMode() && child->GetWindowToken()) {
665                 layoutPolicy_->NotifyClientAndAnimation(child, child->GetWindowRect(), reason);
666                 WLOGI("Notify split window that drag is start or end, Id: "
667                     "%{public}d, reason: %{public}u", child->GetWindowId(), reason);
668             }
669         }
670     } else {
671         layoutPolicy_->NotifyClientAndAnimation(node, node->GetWindowRect(), reason);
672         WLOGI("Notify window that drag is start or end, windowId: %{public}d, "
673             "reason: %{public}u", node->GetWindowId(), reason);
674     }
675 }
676 
UpdateWindowTree(sptr<WindowNode> & node)677 void WindowNodeContainer::UpdateWindowTree(sptr<WindowNode>& node)
678 {
679     HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER);
680     node->priority_ = zorderPolicy_->GetWindowPriority(node->GetWindowType());
681     RaiseInputMethodWindowPriorityIfNeeded(node);
682     RaiseShowWhenLockedWindowIfNeeded(node);
683     ResetMainFloatingWindowPriorityIfNeeded(node);
684     auto parentNode = node->parent_;
685     if (parentNode == nullptr) {
686         WLOGI("Current window node has no parent: %{public}u", node->GetWindowId());
687         return;
688     }
689     auto iter = std::find(parentNode->children_.begin(), parentNode->children_.end(), node);
690     if (iter != parentNode->children_.end()) {
691         WLOGI("node %{public}u already on window tree, not update!", node->GetWindowId());
692         return;
693     }
694     auto position = parentNode->children_.end();
695     int splitWindowCnt = 0;
696     for (auto child = parentNode->children_.begin(); child < parentNode->children_.end(); ++child) {
697         if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE && splitWindowCnt == SPLIT_WINDOWS_CNT) {
698             position = child;
699             break;
700         }
701         if (WindowHelper::IsSplitWindowMode((*child)->GetWindowMode())) {
702             splitWindowCnt++;
703         }
704         if ((*child)->priority_ > node->priority_) {
705             position = child;
706             break;
707         }
708     }
709     parentNode->children_.insert(position, node);
710 }
711 
AddAppSurfaceNodeOnRSTree(sptr<WindowNode> & node)712 bool WindowNodeContainer::AddAppSurfaceNodeOnRSTree(sptr<WindowNode>& node)
713 {
714     /*
715      * App main window must has starting window, and show after starting window
716      * Starting Window has already update leashWindowSurfaceNode and starting window surfaceNode on RSTree
717      * Just need add appSurface Node as child of leashWindowSurfaceNode
718      */
719     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "AddAppSurfaceNodeOnRSTree(%u)", node->GetWindowId());
720     if (!WindowHelper::IsMainWindow(node->GetWindowType())) {
721         WLOGFE("id:%{public}u not main app window but has start window", node->GetWindowId());
722         return false;
723     }
724     if (!node->leashWinSurfaceNode_ || !node->surfaceNode_) {
725         WLOGFE("id:%{public}u leashWinSurfaceNode or surfaceNode is null but has start window!", node->GetWindowId());
726         return false;
727     }
728     WLOGI("AddAppSurfaceNodeOnRSTree Id: %{public}d", node->GetWindowId());
729     if (!node->currentVisibility_) {
730         WLOGI("id: %{public}d is invisible, no need update RS tree", node->GetWindowId());
731         return false;
732     }
733     node->leashWinSurfaceNode_->AddChild(node->surfaceNode_, -1);
734     return true;
735 }
736 
OpenInputMethodSyncTransaction()737 void WindowNodeContainer::OpenInputMethodSyncTransaction()
738 {
739     if (!isAnimateTransactionEnabled_) {
740         WLOGD("InputMethodSyncTransaction is not enabled");
741         return;
742     }
743     // Before open transaction, it must flush first.
744     auto transactionProxy = RSTransactionProxy::GetInstance();
745     if (!transactionProxy) {
746         return;
747     }
748     transactionProxy->FlushImplicitTransaction();
749     auto syncTransactionController = RSSyncTransactionController::GetInstance();
750     if (syncTransactionController) {
751         syncTransactionController->OpenSyncTransaction();
752     }
753     WLOGD("OpenInputMethodSyncTransaction");
754 }
755 
IsWindowFollowParent(WindowType type)756 bool WindowNodeContainer::IsWindowFollowParent(WindowType type)
757 {
758     auto isPhone = system::GetParameter("const.product.devicetype", "unknown") == "phone";
759     if (!isPhone) {
760         return false;
761     }
762     return WindowHelper::IsWindowFollowParent(type);
763 }
764 
AddNodeOnRSTree(sptr<WindowNode> & node,DisplayId displayId,DisplayId parentDisplayId,WindowUpdateType type,bool animationPlayed)765 bool WindowNodeContainer::AddNodeOnRSTree(sptr<WindowNode>& node, DisplayId displayId, DisplayId parentDisplayId,
766     WindowUpdateType type, bool animationPlayed)
767 {
768     HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER);
769     if (node->GetWindowProperty()->GetAnimationFlag() == static_cast<uint32_t>(WindowAnimation::CUSTOM) ||
770         node->GetWindowType() == WindowType::WINDOW_TYPE_APP_COMPONENT) {
771         WLOGI("no need to update RSTree");
772         return true;
773     }
774     bool isMultiDisplay = layoutPolicy_->IsMultiDisplay();
775     WLOGFD("Id: %{public}d, displayId: %{public}" PRIu64", parentDisplayId: %{public}" PRIu64", "
776         "isMultiDisplay: %{public}d, animationPlayed: %{public}d",
777         node->GetWindowId(), displayId, parentDisplayId, isMultiDisplay, animationPlayed);
778     auto updateRSTreeFunc = [&]() {
779         if (!node->currentVisibility_) {
780             WLOGI("id: %{public}d invisible, no need update RS tree", node->GetWindowId());
781             return;
782         }
783 
784         if (IsWindowFollowParent(node->GetWindowType())) {
785             auto& parentNode = node->parent_;
786             if (parentNode != nullptr && parentNode->surfaceNode_ != nullptr &&
787                 node->surfaceNode_ != nullptr) {
788                 node->surfaceNode_->SetTranslateX(node->GetWindowRect().posX_ - parentNode->GetWindowRect().posX_);
789                 node->surfaceNode_->SetTranslateY(node->GetWindowRect().posY_ - parentNode->GetWindowRect().posY_);
790                 node->surfaceNode_->SetVisible(true);
791                 parentNode->surfaceNode_->AddChild(node->surfaceNode_, -1);
792                 WLOGFD("Add surfaceNode to parent surfaceNode succeed.");
793                 return;
794             }
795         }
796         auto& dms = DisplayManagerServiceInner::GetInstance();
797         auto& surfaceNode = node->leashWinSurfaceNode_ != nullptr ? node->leashWinSurfaceNode_ : node->surfaceNode_;
798         dms.UpdateRSTree(displayId, parentDisplayId, surfaceNode, true, isMultiDisplay);
799         for (auto& child : node->children_) {
800             if (child->currentVisibility_ && !IsWindowFollowParent(child->GetWindowType())) {
801                 dms.UpdateRSTree(displayId, parentDisplayId, child->surfaceNode_, true, isMultiDisplay);
802             }
803         }
804     };
805 
806     if (type != WindowUpdateType::WINDOW_UPDATE_ADDED && type != WindowUpdateType::WINDOW_UPDATE_REMOVED) {
807         updateRSTreeFunc();
808         return true;
809     }
810 
811     WindowGravity windowGravity;
812     uint32_t percent;
813     node->GetWindowGravity(windowGravity, percent);
814     if (node->EnableDefaultAnimation(animationPlayed)) {
815         WLOGFD("Add node with animation");
816         StartTraceArgs(HITRACE_TAG_WINDOW_MANAGER, "Animate(%u)", node->GetWindowId());
817         RSNode::Animate(animationConfig_.windowAnimationConfig_.animationTiming_.timingProtocol_,
818             animationConfig_.windowAnimationConfig_.animationTiming_.timingCurve_, updateRSTreeFunc);
819         FinishTrace(HITRACE_TAG_WINDOW_MANAGER);
820     } else if (node->GetWindowType() == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT &&
821         windowGravity != WindowGravity::WINDOW_GRAVITY_FLOAT &&
822         !animationPlayed) { // add keyboard with animation
823         auto timingProtocol = animationConfig_.keyboardAnimationConfig_.durationIn_;
824         OpenInputMethodSyncTransaction();
825         RSNode::Animate(timingProtocol, animationConfig_.keyboardAnimationConfig_.curve_, updateRSTreeFunc);
826     } else {
827         WLOGFD("add node without animation");
828         updateRSTreeFunc();
829     }
830     return true;
831 }
832 
RemoveNodeFromRSTree(sptr<WindowNode> & node,DisplayId displayId,DisplayId parentDisplayId,WindowUpdateType type,bool animationPlayed)833 bool WindowNodeContainer::RemoveNodeFromRSTree(sptr<WindowNode>& node, DisplayId displayId, DisplayId parentDisplayId,
834     WindowUpdateType type, bool animationPlayed)
835 {
836     HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER);
837     if (node->GetWindowProperty()->GetAnimationFlag() == static_cast<uint32_t>(WindowAnimation::CUSTOM) ||
838         node->GetWindowType() == WindowType::WINDOW_TYPE_APP_COMPONENT) {
839         WLOGI("no need to update RSTree");
840         return true;
841     }
842     bool isMultiDisplay = layoutPolicy_->IsMultiDisplay();
843     WLOGFD("Id: %{public}d, displayId: %{public}" PRIu64", isMultiDisplay: %{public}d, "
844         "parentDisplayId: %{public}" PRIu64", animationPlayed: %{public}d",
845         node->GetWindowId(), displayId, isMultiDisplay, parentDisplayId, animationPlayed);
846     auto updateRSTreeFunc = [&]() {
847         if (IsWindowFollowParent(node->GetWindowType())) {
848             const auto& parentNode = node->parent_;
849             if (parentNode != nullptr && parentNode->surfaceNode_ != nullptr &&
850                 node->surfaceNode_ != nullptr) {
851                 node->surfaceNode_->SetVisible(false);
852                 parentNode->surfaceNode_->RemoveChild(node->surfaceNode_);
853                 WLOGFD("Remove surfaceNode to parent surfaceNode succeed.");
854                 return;
855             }
856         }
857         auto& dms = DisplayManagerServiceInner::GetInstance();
858         auto& surfaceNode = node->leashWinSurfaceNode_ != nullptr ? node->leashWinSurfaceNode_ : node->surfaceNode_;
859         dms.UpdateRSTree(displayId, parentDisplayId, surfaceNode, false, isMultiDisplay);
860         for (auto& child : node->children_) {
861             if (child->currentVisibility_ && !IsWindowFollowParent(child->GetWindowType())) {
862                 dms.UpdateRSTree(displayId, parentDisplayId, child->surfaceNode_, false, isMultiDisplay);
863             }
864         }
865     };
866 
867     if (type != WindowUpdateType::WINDOW_UPDATE_ADDED && type != WindowUpdateType::WINDOW_UPDATE_REMOVED) {
868         updateRSTreeFunc();
869         return true;
870     }
871 
872     WindowGravity windowGravity;
873     uint32_t percent;
874     node->GetWindowGravity(windowGravity, percent);
875     if (node->EnableDefaultAnimation(animationPlayed)) {
876         WLOGFD("remove with animation");
877         StartTraceArgs(HITRACE_TAG_WINDOW_MANAGER, "Animate(%u)", node->GetWindowId());
878         if (node->surfaceNode_) {
879             node->surfaceNode_->SetFreeze(true);
880         }
881         wptr<WindowNode> weakNode(node);
882         RSNode::Animate(animationConfig_.windowAnimationConfig_.animationTiming_.timingProtocol_,
883             animationConfig_.windowAnimationConfig_.animationTiming_.timingCurve_, updateRSTreeFunc, [weakNode]() {
884             auto weakWindow = weakNode.promote();
885             if (weakWindow && weakWindow->surfaceNode_) {
886                 weakWindow->surfaceNode_->SetFreeze(false);
887             }
888         });
889         FinishTrace(HITRACE_TAG_WINDOW_MANAGER);
890     } else if (node->GetWindowType() == WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT &&
891         windowGravity != WindowGravity::WINDOW_GRAVITY_FLOAT && !animationPlayed) {
892         // remove keyboard with animation
893         OpenInputMethodSyncTransaction();
894         auto timingProtocol = animationConfig_.keyboardAnimationConfig_.durationOut_;
895         RSNode::Animate(timingProtocol, animationConfig_.keyboardAnimationConfig_.curve_, updateRSTreeFunc);
896     } else {
897         updateRSTreeFunc();
898     }
899     return true;
900 }
901 
Destroy()902 const std::vector<uint32_t>& WindowNodeContainer::Destroy()
903 {
904     // clear vector cache completely, swap with empty vector
905     auto emptyVector = std::vector<uint32_t>();
906     removedIds_.swap(emptyVector);
907     for (auto& node : belowAppWindowNode_->children_) {
908         DestroyWindowNode(node, removedIds_);
909     }
910     for (auto& node : appWindowNode_->children_) {
911         DestroyWindowNode(node, removedIds_);
912     }
913     for (auto& node : aboveAppWindowNode_->children_) {
914         DestroyWindowNode(node, removedIds_);
915     }
916     return removedIds_;
917 }
918 
FindRoot(WindowType type) const919 sptr<WindowNode> WindowNodeContainer::FindRoot(WindowType type) const
920 {
921     if (WindowHelper::IsAppWindow(type) || type == WindowType::WINDOW_TYPE_DOCK_SLICE ||
922         type == WindowType::WINDOW_TYPE_APP_COMPONENT || type == WindowType::WINDOW_TYPE_PLACEHOLDER ||
923         type == WindowType::WINDOW_TYPE_DIALOG) {
924         return appWindowNode_;
925     }
926     if (WindowHelper::IsBelowSystemWindow(type)) {
927         return belowAppWindowNode_;
928     }
929     if (WindowHelper::IsAboveSystemWindow(type)) {
930         return aboveAppWindowNode_;
931     }
932     return nullptr;
933 }
934 
FindWindowNodeById(uint32_t id) const935 sptr<WindowNode> WindowNodeContainer::FindWindowNodeById(uint32_t id) const
936 {
937     std::vector<sptr<WindowNode>> rootNodes = { aboveAppWindowNode_, appWindowNode_, belowAppWindowNode_ };
938     for (const auto& rootNode : rootNodes) {
939         for (auto& node : rootNode->children_) {
940             if (node->GetWindowId() == id) {
941                 return node;
942             }
943             for (auto& subNode : node->children_) {
944                 if (subNode->GetWindowId() == id) {
945                     return subNode;
946                 }
947             }
948         }
949     }
950     return nullptr;
951 }
952 
UpdateFocusStatus(uint32_t id,bool focused)953 void WindowNodeContainer::UpdateFocusStatus(uint32_t id, bool focused)
954 {
955     auto node = FindWindowNodeById(id);
956     if (node == nullptr) {
957         WLOGFW("cannot find focused window id:%{public}d", id);
958         return;
959     }
960     if (focused) {
961         focusedPid_ = node->GetCallingPid();
962     }
963     node->isFocused_ = focused;
964     // change focus window shadow
965     WindowSystemEffect::SetWindowShadow(node);
966     if (node->GetCallingPid() == 0) {
967         WLOGFW("focused window is starting window, no need notify");
968         return;
969     }
970 
971     if (focused && node->GetWindowProperty() != nullptr) {
972         AbilityInfo info = node->GetWindowProperty()->GetAbilityInfo();
973         WLOGFD("current focus window: windowId: %{public}d, windowName: %{public}s, bundleName: %{public}s,"
974             " abilityName: %{public}s, pid: %{public}d, uid: %{public}d", id,
975             node->GetWindowProperty()->GetWindowName().c_str(), info.bundleName_.c_str(), info.abilityName_.c_str(),
976             node->GetCallingPid(), node->GetCallingUid());
977         uint64_t focusNodeId = 0; // 0 means invalid
978         if (node->surfaceNode_ == nullptr) {
979             WLOGFW("focused window surfaceNode is null");
980         } else {
981             focusNodeId = node->surfaceNode_->GetId();
982         }
983         FocusAppInfo appInfo =
984             { node->GetCallingPid(), node->GetCallingUid(), info.bundleName_, info.abilityName_, focusNodeId };
985         RSInterfaces::GetInstance().SetFocusAppInfo(appInfo);
986     }
987     if (node->GetWindowToken()) {
988         node->GetWindowToken()->UpdateFocusStatus(focused);
989     }
990     if (node->abilityToken_ == nullptr) {
991         WLOGW("AbilityToken is null, window : %{public}d", id);
992     }
993     sptr<FocusChangeInfo> focusChangeInfo = new FocusChangeInfo(node->GetWindowId(), node->GetDisplayId(),
994         node->GetCallingPid(), node->GetCallingUid(), node->GetWindowType(), node->abilityToken_);
995     WindowManagerAgentController::GetInstance().UpdateFocusChangeInfo(
996         focusChangeInfo, focused);
997 }
998 
UpdateActiveStatus(uint32_t id,bool isActive)999 void WindowNodeContainer::UpdateActiveStatus(uint32_t id, bool isActive)
1000 {
1001     auto node = FindWindowNodeById(id);
1002     if (node == nullptr) {
1003         WLOGFE("cannot find active window id: %{public}d", id);
1004         return;
1005     }
1006     if (isActive) {
1007         activePid_ = node->GetCallingPid();
1008     }
1009     if (node->GetWindowToken()) {
1010         node->GetWindowToken()->UpdateActiveStatus(isActive);
1011     }
1012 }
1013 
UpdateBrightness(uint32_t id,bool byRemoved)1014 void WindowNodeContainer::UpdateBrightness(uint32_t id, bool byRemoved)
1015 {
1016     auto node = FindWindowNodeById(id);
1017     if (node == nullptr) {
1018         WLOGFE("cannot find active window id: %{public}d", id);
1019         return;
1020     }
1021 
1022     if (!byRemoved) {
1023         if (!WindowHelper::IsAppWindow(node->GetWindowType())) {
1024             return;
1025         }
1026     }
1027     WLOGI("Brightness: [%{public}f, %{public}f]", GetDisplayBrightness(), node->GetBrightness());
1028     if (std::fabs(node->GetBrightness() - UNDEFINED_BRIGHTNESS) < std::numeric_limits<float>::min()) {
1029         if (GetDisplayBrightness() != node->GetBrightness()) {
1030             WLOGI("adjust brightness with default value");
1031             DisplayPowerMgr::DisplayPowerMgrClient::GetInstance().RestoreBrightness();
1032             SetDisplayBrightness(UNDEFINED_BRIGHTNESS); // UNDEFINED_BRIGHTNESS means system default brightness
1033         }
1034         SetBrightnessWindow(INVALID_WINDOW_ID);
1035     } else {
1036         if (GetDisplayBrightness() != node->GetBrightness()) {
1037             WLOGI("adjust brightness with value: %{public}u", ToOverrideBrightness(node->GetBrightness()));
1038             DisplayPowerMgr::DisplayPowerMgrClient::GetInstance().OverrideBrightness(
1039                 ToOverrideBrightness(node->GetBrightness()));
1040             SetDisplayBrightness(node->GetBrightness());
1041         }
1042         SetBrightnessWindow(node->GetWindowId());
1043     }
1044 }
1045 
AssignZOrder()1046 void WindowNodeContainer::AssignZOrder()
1047 {
1048     zOrder_ = 0;
1049     WindowNodeOperationFunc func = [this](sptr<WindowNode> node) {
1050         if (!node->leashWinSurfaceNode_ && !node->surfaceNode_ && !node->startingWinSurfaceNode_) {
1051             ++zOrder_;
1052             WLOGFE("Id: %{public}u has no surface nodes", node->GetWindowId());
1053             return false;
1054         }
1055         if (node->leashWinSurfaceNode_ != nullptr) {
1056             ++zOrder_;
1057             node->leashWinSurfaceNode_->SetPositionZ(zOrder_);
1058         }
1059 
1060         if (node->surfaceNode_ != nullptr) {
1061             ++zOrder_;
1062             node->surfaceNode_->SetPositionZ(zOrder_);
1063             node->zOrder_ = zOrder_;
1064         }
1065         // make sure starting window above app
1066         if (node->startingWinSurfaceNode_ != nullptr) {
1067             ++zOrder_;
1068             node->startingWinSurfaceNode_->SetPositionZ(zOrder_);
1069         }
1070         return false;
1071     };
1072     TraverseWindowTree(func, false);
1073     displayGroupController_->UpdateDisplayGroupWindowTree();
1074 }
1075 
SetFocusWindow(uint32_t windowId)1076 WMError WindowNodeContainer::SetFocusWindow(uint32_t windowId)
1077 {
1078     if (focusedWindow_ == windowId) {
1079         WLOGI("Focus window not change, id: %{public}u, %{public}d", windowId, focusedPid_);
1080         // StartingWindow can be focused and this pid is 0, then notify info in UpdateFocusStatus.
1081         // This info is invalid, so we must notify again when first frame callback.
1082         if (focusedPid_ == 0) {
1083             UpdateFocusStatus(windowId, true);
1084         }
1085         return WMError::WM_DO_NOTHING;
1086     }
1087     UpdateFocusStatus(focusedWindow_, false);
1088     focusedWindow_ = windowId;
1089     UpdateFocusStatus(focusedWindow_, true);
1090     return WMError::WM_OK;
1091 }
1092 
GetFocusWindow() const1093 uint32_t WindowNodeContainer::GetFocusWindow() const
1094 {
1095     return focusedWindow_;
1096 }
1097 
SetActiveWindow(uint32_t windowId,bool byRemoved)1098 WMError WindowNodeContainer::SetActiveWindow(uint32_t windowId, bool byRemoved)
1099 {
1100     if (activeWindow_ == windowId) {
1101         WLOGI("Active window not change, id: %{public}u, %{public}d", windowId, activePid_);
1102         if (activePid_ == 0) {
1103             UpdateActiveStatus(windowId, true);
1104         }
1105         return WMError::WM_DO_NOTHING;
1106     }
1107     UpdateActiveStatus(activeWindow_, false);
1108     activeWindow_ = windowId;
1109     UpdateActiveStatus(activeWindow_, true);
1110     UpdateBrightness(activeWindow_, byRemoved);
1111     return WMError::WM_OK;
1112 }
1113 
SetDisplayBrightness(float brightness)1114 void WindowNodeContainer::SetDisplayBrightness(float brightness)
1115 {
1116     displayBrightness_ = brightness;
1117 }
1118 
GetDisplayBrightness() const1119 float WindowNodeContainer::GetDisplayBrightness() const
1120 {
1121     return displayBrightness_;
1122 }
1123 
SetBrightnessWindow(uint32_t windowId)1124 void WindowNodeContainer::SetBrightnessWindow(uint32_t windowId)
1125 {
1126     brightnessWindow_ = windowId;
1127 }
1128 
GetBrightnessWindow() const1129 uint32_t WindowNodeContainer::GetBrightnessWindow() const
1130 {
1131     return brightnessWindow_;
1132 }
1133 
ToOverrideBrightness(float brightness)1134 uint32_t WindowNodeContainer::ToOverrideBrightness(float brightness)
1135 {
1136     return static_cast<uint32_t>(brightness * MAX_BRIGHTNESS);
1137 }
1138 
GetActiveWindow() const1139 uint32_t WindowNodeContainer::GetActiveWindow() const
1140 {
1141     return activeWindow_;
1142 }
1143 
GetLayoutPolicy() const1144 sptr<WindowLayoutPolicy> WindowNodeContainer::GetLayoutPolicy() const
1145 {
1146     return layoutPolicy_;
1147 }
1148 
GetAvoidController() const1149 sptr<AvoidAreaController> WindowNodeContainer::GetAvoidController() const
1150 {
1151     return avoidController_;
1152 }
1153 
GetDisplayGroupController() const1154 sptr<DisplayGroupController> WindowNodeContainer::GetDisplayGroupController() const
1155 {
1156     return displayGroupController_;
1157 }
1158 
GetRootNode(WindowRootNodeType type) const1159 sptr<WindowNode> WindowNodeContainer::GetRootNode(WindowRootNodeType type) const
1160 {
1161     if (type == WindowRootNodeType::ABOVE_WINDOW_NODE) {
1162         return aboveAppWindowNode_;
1163     } else if (type == WindowRootNodeType::APP_WINDOW_NODE) {
1164         return appWindowNode_;
1165     } else if (type == WindowRootNodeType::BELOW_WINDOW_NODE) {
1166         return belowAppWindowNode_;
1167     }
1168     return nullptr;
1169 }
1170 
HandleKeepScreenOn(const sptr<WindowNode> & node,bool requireLock)1171 void WindowNodeContainer::HandleKeepScreenOn(const sptr<WindowNode>& node, bool requireLock)
1172 {
1173     if (requireLock && node->keepScreenLock_ == nullptr) {
1174         // reset ipc identity
1175         std::string identity = IPCSkeleton::ResetCallingIdentity();
1176         node->keepScreenLock_ = PowerMgr::PowerMgrClient::GetInstance().CreateRunningLock(node->GetWindowName(),
1177             PowerMgr::RunningLockType::RUNNINGLOCK_SCREEN);
1178         // set ipc identity to raw
1179         IPCSkeleton::SetCallingIdentity(identity);
1180     }
1181     if (node->keepScreenLock_ == nullptr) {
1182         return;
1183     }
1184     WLOGI("keep screen on: [%{public}s, %{public}d]", node->GetWindowName().c_str(), requireLock);
1185     HITRACE_METER_FMT(HITRACE_TAG_WINDOW_MANAGER, "container:HandleKeepScreenOn(%s, %d)",
1186         node->GetWindowName().c_str(), requireLock);
1187     ErrCode res;
1188     // reset ipc identity
1189     std::string identity = IPCSkeleton::ResetCallingIdentity();
1190     if (requireLock) {
1191         res = node->keepScreenLock_->Lock();
1192     } else {
1193         res = node->keepScreenLock_->UnLock();
1194     }
1195     // set ipc identity to raw
1196     IPCSkeleton::SetCallingIdentity(identity);
1197     if (res != ERR_OK) {
1198         WLOGFE("handle keep screen running lock failed: [operation: %{public}d, err: %{public}d]", requireLock, res);
1199     }
1200 }
1201 
IsAboveSystemBarNode(sptr<WindowNode> node) const1202 bool WindowNodeContainer::IsAboveSystemBarNode(sptr<WindowNode> node) const
1203 {
1204     int32_t curPriority = zorderPolicy_->GetWindowPriority(node->GetWindowType());
1205     if ((curPriority > zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_STATUS_BAR)) &&
1206         (curPriority > zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_NAVIGATION_BAR))) {
1207         return true;
1208     }
1209     return false;
1210 }
1211 
IsSplitImmersiveNode(sptr<WindowNode> node) const1212 bool WindowNodeContainer::IsSplitImmersiveNode(sptr<WindowNode> node) const
1213 {
1214     auto type = node->GetWindowType();
1215     return node->IsSplitMode() || type == WindowType::WINDOW_TYPE_DOCK_SLICE;
1216 }
1217 
GetExpectImmersiveProperty(DisplayId id,sptr<WindowNode> & triggerWindow) const1218 std::unordered_map<WindowType, SystemBarProperty> WindowNodeContainer::GetExpectImmersiveProperty(DisplayId id,
1219     sptr<WindowNode>& triggerWindow) const
1220 {
1221     std::unordered_map<WindowType, SystemBarProperty> sysBarPropMap {
1222         { WindowType::WINDOW_TYPE_STATUS_BAR,     SystemBarProperty() },
1223         { WindowType::WINDOW_TYPE_NAVIGATION_BAR, SystemBarProperty() },
1224     };
1225 
1226     std::vector<sptr<WindowNode>> rootNodes = { aboveAppWindowNode_, appWindowNode_, belowAppWindowNode_ };
1227     if (layoutMode_ == WindowLayoutMode::TILE) {
1228         rootNodes = { aboveAppWindowNode_, belowAppWindowNode_ };
1229     }
1230 
1231     for (const auto& node : rootNodes) {
1232         for (auto iter = node->children_.rbegin(); iter < node->children_.rend(); ++iter) {
1233             auto& sysBarPropMapNode = (*iter)->GetSystemBarProperty();
1234             if (IsAboveSystemBarNode(*iter)) {
1235                 continue;
1236             }
1237             if (WindowHelper::IsFullScreenWindow((*iter)->GetWindowMode())
1238                 && (*iter)->GetWindowType() != WindowType::WINDOW_TYPE_PANEL) {
1239                 auto displayInfo = DisplayGroupInfo::GetInstance().GetDisplayInfo(id);
1240                 if (displayInfo && WmsUtils::IsExpectedRotateLandscapeWindow((*iter)->GetRequestedOrientation(),
1241                     displayInfo->GetDisplayOrientation(), (*iter)->GetWindowFlags())) {
1242                     WLOGFI("Horizontal window id: %{public}d make it immersive", (*iter)->GetWindowId());
1243                     for (auto it : sysBarPropMap) {
1244                         sysBarPropMap[it.first] = (sysBarPropMapNode.find(it.first))->second;
1245                         sysBarPropMap[it.first].enable_ = false;
1246                     }
1247                 } else {
1248                     WLOGFD("Top immersive window id: %{public}d. Use full immersive prop", (*iter)->GetWindowId());
1249                     for (auto it : sysBarPropMap) {
1250                         sysBarPropMap[it.first] = (sysBarPropMapNode.find(it.first))->second;
1251                     }
1252                     triggerWindow = (*iter);
1253                 }
1254                 return sysBarPropMap;
1255             } else if (IsSplitImmersiveNode(*iter)) {
1256                 WLOGFD("Top split window id: %{public}d. Use split immersive prop", (*iter)->GetWindowId());
1257                 for (auto it : sysBarPropMap) {
1258                     sysBarPropMap[it.first] = (sysBarPropMapNode.find(it.first))->second;
1259                     sysBarPropMap[it.first].enable_ = false;
1260                 }
1261                 return sysBarPropMap;
1262             }
1263         }
1264     }
1265 
1266     WLOGFD("No immersive window on top. Use default systembar Property");
1267     return sysBarPropMap;
1268 }
1269 
NotifyIfAvoidAreaChanged(const sptr<WindowNode> & node,const AvoidControlType avoidType) const1270 void WindowNodeContainer::NotifyIfAvoidAreaChanged(const sptr<WindowNode>& node,
1271     const AvoidControlType avoidType) const
1272 {
1273     auto checkFunc = [this](sptr<WindowNode> node) {
1274         return CheckWindowNodeWhetherInWindowTree(node);
1275     };
1276     avoidController_->ProcessWindowChange(node, avoidType, checkFunc);
1277     if (WindowHelper::IsSystemBarWindow(node->GetWindowType())) {
1278         NotifyIfSystemBarRegionChanged(node->GetDisplayId());
1279     } else {
1280         NotifyIfSystemBarTintChanged(node->GetDisplayId());
1281     }
1282 
1283     NotifyIfKeyboardRegionChanged(node, avoidType);
1284 }
1285 
BeforeProcessWindowAvoidAreaChangeWhenDisplayChange() const1286 void WindowNodeContainer::BeforeProcessWindowAvoidAreaChangeWhenDisplayChange() const
1287 {
1288     avoidController_->SetFlagForProcessWindowChange(true);
1289 }
1290 
ProcessWindowAvoidAreaChangeWhenDisplayChange() const1291 void WindowNodeContainer::ProcessWindowAvoidAreaChangeWhenDisplayChange() const
1292 {
1293     avoidController_->SetFlagForProcessWindowChange(false);
1294     auto checkFunc = [this](sptr<WindowNode> node) {
1295         return CheckWindowNodeWhetherInWindowTree(node);
1296     };
1297     WindowNodeOperationFunc func = [avoidController = avoidController_, &checkFunc](sptr<WindowNode> node) {
1298         avoidController->ProcessWindowChange(node, AvoidControlType::AVOID_NODE_UPDATE, checkFunc);
1299         return false;
1300     };
1301     TraverseWindowTree(func, true);
1302 }
1303 
NotifyIfSystemBarTintChanged(DisplayId displayId) const1304 void WindowNodeContainer::NotifyIfSystemBarTintChanged(DisplayId displayId) const
1305 {
1306     HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER);
1307     sptr<WindowNode> triggerWindow = nullptr;
1308     auto expectSystemBarProp = GetExpectImmersiveProperty(displayId, triggerWindow);
1309     JudgeToReportSystemBarInfo(triggerWindow, expectSystemBarProp);
1310     SystemBarRegionTints tints;
1311     SysBarTintMap& sysBarTintMap = displayGroupController_->sysBarTintMaps_[displayId];
1312     for (auto it : sysBarTintMap) {
1313         auto expectProp = expectSystemBarProp.find(it.first)->second;
1314         if (it.second.prop_ == expectProp) {
1315             continue;
1316         }
1317         WLOGFD("System bar prop update, Type: %{public}d, Visible: %{public}d, Color: %{public}x | %{public}x",
1318             static_cast<int32_t>(it.first), expectProp.enable_, expectProp.backgroundColor_, expectProp.contentColor_);
1319         sysBarTintMap[it.first].prop_ = expectProp;
1320         sysBarTintMap[it.first].type_ = it.first;
1321         tints.emplace_back(sysBarTintMap[it.first]);
1322     }
1323     WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(displayId, tints);
1324 }
1325 
JudgeToReportSystemBarInfo(const sptr<WindowNode> window,const std::unordered_map<WindowType,SystemBarProperty> & systemBarPropInfo) const1326 void WindowNodeContainer::JudgeToReportSystemBarInfo(const sptr<WindowNode> window,
1327     const std::unordered_map<WindowType, SystemBarProperty>& systemBarPropInfo) const
1328 {
1329     if (window == nullptr || !WindowHelper::IsMainWindow(window->GetWindowType())) {
1330         WLOGFD("No need to report");
1331         return;
1332     }
1333 
1334     // 2 means the must size of systemBarPropInfo.
1335     if (systemBarPropInfo.size() != 2) {
1336         return;
1337     }
1338 
1339     auto bundleName = window->abilityInfo_.bundleName_;
1340     auto abilityName = window->abilityInfo_.abilityName_;
1341     auto navigationItor = systemBarPropInfo.find(WindowType::WINDOW_TYPE_NAVIGATION_BAR);
1342     if (navigationItor != systemBarPropInfo.end() && !navigationItor->second.enable_) {
1343         WindowInfoReporter::GetInstance().InsertNavigationBarReportInfo(bundleName, abilityName);
1344         WLOGFD("the navigation bar is disabled by window. windowId:[%{public}u]", window->GetWindowId());
1345     }
1346 }
1347 
NotifyIfSystemBarRegionChanged(DisplayId displayId) const1348 void WindowNodeContainer::NotifyIfSystemBarRegionChanged(DisplayId displayId) const
1349 {
1350     HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER);
1351     SystemBarRegionTints tints;
1352     SysBarTintMap& sysBarTintMap = displayGroupController_->sysBarTintMaps_[displayId];
1353     SysBarNodeMap& sysBarNodeMap = displayGroupController_->sysBarNodeMaps_[displayId];
1354     for (auto it : sysBarTintMap) { // split screen mode not support yet
1355         auto sysNode = sysBarNodeMap[it.first];
1356         if (sysNode == nullptr || it.second.region_ == sysNode->GetWindowRect()) {
1357             continue;
1358         }
1359         const Rect& newRegion = sysNode->GetWindowRect();
1360         sysBarTintMap[it.first].region_ = newRegion;
1361         sysBarTintMap[it.first].type_ = it.first;
1362         tints.emplace_back(sysBarTintMap[it.first]);
1363         WLOGD("system bar region update, type: %{public}d" \
1364             "region: [%{public}d, %{public}d, %{public}d, %{public}d]",
1365             static_cast<int32_t>(it.first), newRegion.posX_, newRegion.posY_, newRegion.width_, newRegion.height_);
1366     }
1367     WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(displayId, tints);
1368 }
1369 
NotifyIfKeyboardRegionChanged(const sptr<WindowNode> & node,const AvoidControlType avoidType) const1370 void WindowNodeContainer::NotifyIfKeyboardRegionChanged(const sptr<WindowNode>& node,
1371     const AvoidControlType avoidType) const
1372 {
1373     WindowGravity windowGravity;
1374     uint32_t percent;
1375     node->GetWindowGravity(windowGravity, percent);
1376     if (node->GetWindowType() != WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT ||
1377         windowGravity == WindowGravity::WINDOW_GRAVITY_FLOAT) {
1378         WLOGFD("windowType: %{public}u", node->GetWindowType());
1379         return;
1380     }
1381 
1382     auto callingWindow = FindWindowNodeById(node->GetCallingWindow());
1383     if (callingWindow == nullptr) {
1384         WLOGD("callingWindow: %{public}u does not be set", node->GetCallingWindow());
1385         callingWindow = FindWindowNodeById(GetFocusWindow());
1386     }
1387     if (callingWindow == nullptr || callingWindow->GetWindowToken() == nullptr) {
1388         WLOGE("does not have correct callingWindow for input method window");
1389         return;
1390     }
1391     const WindowMode callingWindowMode = callingWindow->GetWindowMode();
1392     if (callingWindowMode == WindowMode::WINDOW_MODE_FULLSCREEN ||
1393         callingWindowMode == WindowMode::WINDOW_MODE_SPLIT_PRIMARY ||
1394         callingWindowMode == WindowMode::WINDOW_MODE_SPLIT_SECONDARY) {
1395         const Rect keyRect = node->GetWindowRect();
1396         const Rect callingRect = callingWindow->GetWindowRect();
1397         if (WindowHelper::IsEmptyRect(WindowHelper::GetOverlap(callingRect, keyRect, 0, 0))) {
1398             WLOGFD("no overlap between two windows");
1399             return;
1400         }
1401         Rect overlapRect = { 0, 0, 0, 0 };
1402         if (avoidType == AvoidControlType::AVOID_NODE_ADD || avoidType == AvoidControlType::AVOID_NODE_UPDATE) {
1403             overlapRect = WindowHelper::GetOverlap(keyRect, callingRect, callingRect.posX_, callingRect.posY_);
1404         }
1405 
1406         sptr<OccupiedAreaChangeInfo> info = new OccupiedAreaChangeInfo(OccupiedAreaType::TYPE_INPUT, overlapRect);
1407         if (isAnimateTransactionEnabled_) {
1408             auto syncTransactionController = RSSyncTransactionController::GetInstance();
1409             if (syncTransactionController) {
1410                 callingWindow->GetWindowToken()->UpdateOccupiedAreaChangeInfo(info,
1411                     syncTransactionController->GetRSTransaction());
1412             }
1413         } else {
1414             callingWindow->GetWindowToken()->UpdateOccupiedAreaChangeInfo(info);
1415         }
1416 
1417         WLOGD("keyboard size change callingWindow: [%{public}s, %{public}u], "
1418             "overlap rect: [%{public}d, %{public}d, %{public}u, %{public}u]",
1419             callingWindow->GetWindowName().c_str(), callingWindow->GetWindowId(),
1420             overlapRect.posX_, overlapRect.posY_, overlapRect.width_, overlapRect.height_);
1421         return;
1422     }
1423     WLOGFE("does not have correct callingWindowMode for input method window");
1424 }
1425 
NotifySystemBarTints(std::vector<DisplayId> displayIdVec)1426 void WindowNodeContainer::NotifySystemBarTints(std::vector<DisplayId> displayIdVec)
1427 {
1428     if (displayIdVec.size() != displayGroupController_->sysBarTintMaps_.size()) {
1429         WLOGE("[Immersive] the number of display is error");
1430     }
1431 
1432     for (auto displayId : displayIdVec) {
1433         SystemBarRegionTints tints;
1434         SysBarTintMap& sysBarTintMap = displayGroupController_->sysBarTintMaps_[displayId];
1435         for (auto it : sysBarTintMap) {
1436             WLOGI("[Immersive] systembar tints, T: %{public}d, " \
1437                 "V: %{public}d, C: %{public}x | %{public}x, " \
1438                 "R: [%{public}d, %{public}d, %{public}d, %{public}d]",
1439                 static_cast<int32_t>(it.first),
1440                 sysBarTintMap[it.first].prop_.enable_,
1441                 sysBarTintMap[it.first].prop_.backgroundColor_, sysBarTintMap[it.first].prop_.contentColor_,
1442                 sysBarTintMap[it.first].region_.posX_, sysBarTintMap[it.first].region_.posY_,
1443                 sysBarTintMap[it.first].region_.width_, sysBarTintMap[it.first].region_.height_);
1444             tints.push_back(sysBarTintMap[it.first]);
1445         }
1446         WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(displayId, tints);
1447     }
1448 }
1449 
NotifyDockWindowStateChanged(sptr<WindowNode> & node,bool isEnable)1450 void WindowNodeContainer::NotifyDockWindowStateChanged(sptr<WindowNode>& node, bool isEnable)
1451 {
1452     HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER);
1453     WLOGFD("[Immersive] begin isEnable: %{public}d", isEnable);
1454     if (isEnable) {
1455         for (auto& windowNode : appWindowNode_->children_) {
1456             if (windowNode->GetWindowId() == node->GetWindowId()) {
1457                 continue;
1458             }
1459             if (!WindowHelper::IsFloatingWindow(windowNode->GetWindowMode())) {
1460                 return;
1461             }
1462         }
1463     }
1464     SystemBarProperty prop;
1465     prop.enable_ = isEnable;
1466     SystemBarRegionTint tint;
1467     tint.type_ = WindowType::WINDOW_TYPE_LAUNCHER_DOCK;
1468     tint.prop_ = prop;
1469     SystemBarRegionTints tints;
1470     tints.push_back(tint);
1471     WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(node->GetDisplayId(), tints);
1472 }
1473 
NotifyDockWindowStateChanged(DisplayId displayId)1474 void WindowNodeContainer::NotifyDockWindowStateChanged(DisplayId displayId)
1475 {
1476     HITRACE_METER(HITRACE_TAG_WINDOW_MANAGER);
1477     bool isEnable = true;
1478     for (auto& windowNode : appWindowNode_->children_) {
1479         if (WindowHelper::IsSplitWindowMode(windowNode->GetWindowMode()) ||
1480             WindowHelper::IsFullScreenWindow(windowNode->GetWindowMode())) {
1481             isEnable = false;
1482             break;
1483         }
1484     }
1485     WLOGFD("[Immersive] display %{public}" PRIu64" begin isEnable: %{public}d", displayId, isEnable);
1486     SystemBarProperty prop;
1487     prop.enable_ = isEnable;
1488     SystemBarRegionTint tint;
1489     tint.type_ = WindowType::WINDOW_TYPE_LAUNCHER_DOCK;
1490     tint.prop_ = prop;
1491     SystemBarRegionTints tints;
1492     tints.push_back(tint);
1493     WindowManagerAgentController::GetInstance().UpdateSystemBarRegionTints(displayId, tints);
1494 }
1495 
UpdateAvoidAreaListener(sptr<WindowNode> & windowNode,bool haveAvoidAreaListener)1496 void WindowNodeContainer::UpdateAvoidAreaListener(sptr<WindowNode>& windowNode, bool haveAvoidAreaListener)
1497 {
1498     avoidController_->UpdateAvoidAreaListener(windowNode, haveAvoidAreaListener);
1499 }
1500 
IsTopWindow(uint32_t windowId,sptr<WindowNode> & rootNode) const1501 bool WindowNodeContainer::IsTopWindow(uint32_t windowId, sptr<WindowNode>& rootNode) const
1502 {
1503     if (rootNode->children_.empty()) {
1504         WLOGFE("root does not have any node");
1505         return false;
1506     }
1507     auto node = *(rootNode->children_.rbegin());
1508     if (node == nullptr) {
1509         WLOGFE("window tree does not have any node");
1510         return false;
1511     }
1512 
1513     for (auto iter = node->children_.rbegin(); iter < node->children_.rend(); iter++) {
1514         if ((*iter)->priority_ > 0) {
1515             return (*iter)->GetWindowId() == windowId;
1516         } else {
1517             break;
1518         }
1519     }
1520     return node->GetWindowId() == windowId;
1521 }
1522 
RaiseOrderedWindowToTop(std::vector<sptr<WindowNode>> & orderedNodes,std::vector<sptr<WindowNode>> & windowNodes)1523 void WindowNodeContainer::RaiseOrderedWindowToTop(std::vector<sptr<WindowNode>>& orderedNodes,
1524     std::vector<sptr<WindowNode>>& windowNodes)
1525 {
1526     for (auto iter = appWindowNode_->children_.begin(); iter != appWindowNode_->children_.end();) {
1527         uint32_t wid = (*iter)->GetWindowId();
1528         auto orderedIter = std::find_if(orderedNodes.begin(), orderedNodes.end(),
1529             [wid] (sptr<WindowNode> orderedNode) { return orderedNode->GetWindowId() == wid; });
1530         if (orderedIter != orderedNodes.end()) {
1531             iter = windowNodes.erase(iter);
1532         } else {
1533             iter++;
1534         }
1535     }
1536     for (auto iter = orderedNodes.begin(); iter != orderedNodes.end(); iter++) {
1537         UpdateWindowTree(*iter);
1538     }
1539     return;
1540 }
1541 
RaiseWindowToTop(uint32_t windowId,std::vector<sptr<WindowNode>> & windowNodes)1542 void WindowNodeContainer::RaiseWindowToTop(uint32_t windowId, std::vector<sptr<WindowNode>>& windowNodes)
1543 {
1544     if (windowNodes.empty()) {
1545         WLOGFE("windowNodes is empty!");
1546         return;
1547     }
1548     auto iter = std::find_if(windowNodes.begin(), windowNodes.end(),
1549                              [windowId](sptr<WindowNode> node) {
1550                                  return node->GetWindowId() == windowId;
1551                              });
1552     // raise app node window to top
1553     if (iter != windowNodes.end()) {
1554         sptr<WindowNode> node = *iter;
1555         windowNodes.erase(iter);
1556         UpdateWindowTree(node);
1557         WLOGD("raise window to top %{public}u", node->GetWindowId());
1558     }
1559 }
1560 
TraverseContainer(std::vector<sptr<WindowNode>> & windowNodes) const1561 void WindowNodeContainer::TraverseContainer(std::vector<sptr<WindowNode>>& windowNodes) const
1562 {
1563     for (auto& node : belowAppWindowNode_->children_) {
1564         TraverseWindowNode(node, windowNodes);
1565     }
1566     for (auto& node : appWindowNode_->children_) {
1567         TraverseWindowNode(node, windowNodes);
1568     }
1569     for (auto& node : aboveAppWindowNode_->children_) {
1570         TraverseWindowNode(node, windowNodes);
1571     }
1572     std::reverse(windowNodes.begin(), windowNodes.end());
1573 }
1574 
TraverseWindowNode(sptr<WindowNode> & node,std::vector<sptr<WindowNode>> & windowNodes) const1575 void WindowNodeContainer::TraverseWindowNode(sptr<WindowNode>& node, std::vector<sptr<WindowNode>>& windowNodes) const
1576 {
1577     if (node == nullptr) {
1578         return;
1579     }
1580     auto iter = node->children_.begin();
1581     for (; iter < node->children_.end(); ++iter) {
1582         if ((*iter)->priority_ < 0) {
1583             windowNodes.emplace_back(*iter);
1584         } else {
1585             break;
1586         }
1587     }
1588     windowNodes.emplace_back(node);
1589     for (; iter < node->children_.end(); ++iter) {
1590         windowNodes.emplace_back(*iter);
1591     }
1592 }
1593 
GetAvoidAreaByType(const sptr<WindowNode> & node,AvoidAreaType avoidAreaType) const1594 AvoidArea WindowNodeContainer::GetAvoidAreaByType(const sptr<WindowNode>& node, AvoidAreaType avoidAreaType) const
1595 {
1596     if (CheckWindowNodeWhetherInWindowTree(node)) {
1597         return avoidController_->GetAvoidAreaByType(node, avoidAreaType);
1598     }
1599     return {};
1600 }
1601 
CheckWindowNodeWhetherInWindowTree(const sptr<WindowNode> & node) const1602 bool WindowNodeContainer::CheckWindowNodeWhetherInWindowTree(const sptr<WindowNode>& node) const
1603 {
1604     bool isInWindowTree = false;
1605     WindowNodeOperationFunc func = [&node, &isInWindowTree](sptr<WindowNode> windowNode) {
1606         if (node->GetWindowId() == windowNode->GetWindowId()) {
1607             isInWindowTree = true;
1608             return true;
1609         }
1610         return false;
1611     };
1612     TraverseWindowTree(func, true);
1613     return isInWindowTree;
1614 }
1615 
DumpScreenWindowTreeByWinId(uint32_t winid)1616 void WindowNodeContainer::DumpScreenWindowTreeByWinId(uint32_t winid)
1617 {
1618     WLOGFD("------ dump window info begin -------");
1619     WLOGFD("WindowName WinId Type Mode ZOrd [   x    y    w    h]");
1620     uint32_t zOrder = zOrder_;
1621     WindowNodeOperationFunc func = [&zOrder, &winid](sptr<WindowNode> node) {
1622         Rect rect = node->GetWindowRect();
1623         uint32_t windowId = node->GetWindowId();
1624         const std::string& windowName = node->GetWindowName().size() < WINDOW_NAME_MAX_LENGTH ?
1625             node->GetWindowName() : node->GetWindowName().substr(0, WINDOW_NAME_MAX_LENGTH);
1626         if (winid == windowId) {
1627             WLOGD("DumpScreenWindowTree: %{public}10s  %{public}5u %{public}4u %{public}4u "
1628                 "%{public}4u [%{public}4d %{public}4d %{public}4u %{public}4u]",
1629                 windowName.c_str(), node->GetWindowId(), node->GetWindowType(), node->GetWindowMode(),
1630                 --zOrder, rect.posX_, rect.posY_, rect.width_, rect.height_);
1631         } else {
1632             WLOGD("DumpScreenWindowTree: %{public}10s  %{public}5u %{public}4u %{public}4u "
1633                 "%{public}4u [%{public}4d %{public}4d %{public}4u %{public}4u]",
1634                 windowName.c_str(), node->GetWindowId(), node->GetWindowType(), node->GetWindowMode(),
1635                 --zOrder, rect.posX_, rect.posY_, rect.width_, rect.height_);
1636         }
1637         return false;
1638     };
1639     TraverseWindowTree(func, true);
1640     WLOGFD("------ dump window info end -------");
1641 }
1642 
DumpScreenWindowTree()1643 void WindowNodeContainer::DumpScreenWindowTree()
1644 {
1645     WLOGD("------ dump window info begin -------");
1646     WLOGD("WindowName DisplayId WinId Type Mode Flag ZOrd Orientation firstFrameCallback [   x    y    w    h]");
1647     uint32_t zOrder = zOrder_;
1648     WindowNodeOperationFunc func = [&zOrder](sptr<WindowNode> node) {
1649         Rect rect = node->GetWindowRect();
1650         const std::string& windowName = node->GetWindowName().size() < WINDOW_NAME_MAX_LENGTH ?
1651             node->GetWindowName() : node->GetWindowName().substr(0, WINDOW_NAME_MAX_LENGTH);
1652         WLOGD("DumpScreenWindowTree: %{public}10s %{public}9" PRIu64" %{public}5u %{public}4u %{public}4u %{public}4u "
1653             "%{public}4u %{public}11u %{public}12d [%{public}4d %{public}4d %{public}4u %{public}4u]",
1654             windowName.c_str(), node->GetDisplayId(), node->GetWindowId(), node->GetWindowType(), node->GetWindowMode(),
1655             node->GetWindowFlags(), --zOrder, static_cast<uint32_t>(node->GetRequestedOrientation()),
1656             node->firstFrameAvailable_, rect.posX_, rect.posY_, rect.width_, rect.height_);
1657         return false;
1658     };
1659     TraverseWindowTree(func, true);
1660     WLOGD("------ dump window info end -------");
1661 }
1662 
IsVerticalDisplay(DisplayId displayId) const1663 bool WindowNodeContainer::IsVerticalDisplay(DisplayId displayId) const
1664 {
1665     return DisplayGroupInfo::GetInstance().GetDisplayRect(displayId).width_ <
1666         DisplayGroupInfo::GetInstance().GetDisplayRect(displayId).height_;
1667 }
1668 
ProcessWindowStateChange(WindowState state,WindowStateChangeReason reason)1669 void WindowNodeContainer::ProcessWindowStateChange(WindowState state, WindowStateChangeReason reason)
1670 {
1671     switch (reason) {
1672         case WindowStateChangeReason::KEYGUARD: {
1673             int32_t topPriority = zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_KEYGUARD);
1674             TraverseAndUpdateWindowState(state, topPriority);
1675             break;
1676         }
1677         default:
1678             return;
1679     }
1680 }
1681 
TraverseAndUpdateWindowState(WindowState state,int32_t topPriority)1682 void WindowNodeContainer::TraverseAndUpdateWindowState(WindowState state, int32_t topPriority)
1683 {
1684     std::vector<sptr<WindowNode>> rootNodes = { belowAppWindowNode_, appWindowNode_, aboveAppWindowNode_ };
1685     for (auto& node : rootNodes) {
1686         UpdateWindowState(node, topPriority, state);
1687     }
1688 }
1689 
UpdateWindowState(sptr<WindowNode> node,int32_t topPriority,WindowState state)1690 void WindowNodeContainer::UpdateWindowState(sptr<WindowNode> node, int32_t topPriority, WindowState state)
1691 {
1692     if (node == nullptr) {
1693         return;
1694     }
1695     if (node->parent_ != nullptr && node->currentVisibility_) {
1696         if (node->priority_ < topPriority && !WindowHelper::IsShowWhenLocked(node->GetWindowFlags()) &&
1697             !WindowHelper::IsShowWhenLocked(node->parent_->GetWindowFlags())) {
1698             if (node->GetWindowToken()) {
1699                 node->GetWindowToken()->UpdateWindowState(state);
1700             }
1701             HandleKeepScreenOn(node, state);
1702         }
1703     }
1704     for (auto& childNode : node->children_) {
1705         UpdateWindowState(childNode, topPriority, state);
1706     }
1707 }
1708 
HandleKeepScreenOn(const sptr<WindowNode> & node,WindowState state)1709 void WindowNodeContainer::HandleKeepScreenOn(const sptr<WindowNode>& node, WindowState state)
1710 {
1711     if (node == nullptr) {
1712         WLOGFE("window is invalid");
1713         return;
1714     }
1715     if (state == WindowState::STATE_FROZEN) {
1716         HandleKeepScreenOn(node, false);
1717     } else if (state == WindowState::STATE_UNFROZEN) {
1718         HandleKeepScreenOn(node, node->IsKeepScreenOn());
1719     } else {
1720         // do nothing
1721     }
1722 }
1723 
FindDividerNode() const1724 sptr<WindowNode> WindowNodeContainer::FindDividerNode() const
1725 {
1726     for (auto iter = appWindowNode_->children_.begin(); iter != appWindowNode_->children_.end(); iter++) {
1727         if ((*iter)->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
1728             return *iter;
1729         }
1730     }
1731     return nullptr;
1732 }
1733 
RaiseSplitRelatedWindowToTop(sptr<WindowNode> & node)1734 void WindowNodeContainer::RaiseSplitRelatedWindowToTop(sptr<WindowNode>& node)
1735 {
1736     if (node == nullptr) {
1737         return;
1738     }
1739     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(node->GetDisplayId());
1740     if (windowPair == nullptr) {
1741         WLOGFE("Window pair is nullptr");
1742         return;
1743     }
1744     std::vector<sptr<WindowNode>> orderedPair = windowPair->GetOrderedPair(node);
1745     RaiseOrderedWindowToTop(orderedPair, appWindowNode_->children_);
1746     AssignZOrder();
1747     return;
1748 }
1749 
RaiseZOrderForAppWindow(sptr<WindowNode> & node,sptr<WindowNode> & parentNode)1750 WMError WindowNodeContainer::RaiseZOrderForAppWindow(sptr<WindowNode>& node, sptr<WindowNode>& parentNode)
1751 {
1752     if (node == nullptr) {
1753         return WMError::WM_ERROR_NULLPTR;
1754     }
1755     if (IsTopWindow(node->GetWindowId(), appWindowNode_) || IsTopWindow(node->GetWindowId(), aboveAppWindowNode_)) {
1756         WLOGE("Window %{public}u is already at top", node->GetWindowId());
1757         return WMError::WM_ERROR_INVALID_TYPE;
1758     }
1759 
1760     if (WindowHelper::IsSubWindow(node->GetWindowType()) ||
1761         (node->GetWindowType() == WindowType::WINDOW_TYPE_DIALOG)) {
1762         if (parentNode == nullptr) {
1763             WLOGFE("window type is invalid");
1764             return WMError::WM_ERROR_NULLPTR;
1765         }
1766         RaiseWindowToTop(node->GetWindowId(), parentNode->children_); // raise itself
1767         if (parentNode->IsSplitMode()) {
1768             RaiseSplitRelatedWindowToTop(parentNode);
1769         } else if (parentNode->parent_ != nullptr) {
1770             RaiseWindowToTop(parentNode->GetWindowId(), parentNode->parent_->children_); // raise parent window
1771         }
1772     } else if (WindowHelper::IsMainWindow(node->GetWindowType())) {
1773         if (node->IsSplitMode()) {
1774             RaiseSplitRelatedWindowToTop(node);
1775         } else {
1776             // remote animation continuous start and exit allow parent is nullptr
1777             if (node->parent_ == nullptr) {
1778                 WLOGFW("node parent is nullptr");
1779                 return WMError::WM_OK;
1780             }
1781             RaiseWindowToTop(node->GetWindowId(), node->parent_->children_);
1782         }
1783     } else {
1784         // do nothing
1785     }
1786 
1787     AssignZOrder();
1788     WLOGI("Raise app window zorder");
1789     DumpScreenWindowTreeByWinId(node->GetWindowId());
1790     return WMError::WM_OK;
1791 }
1792 
GetNextFocusableWindow(uint32_t windowId) const1793 sptr<WindowNode> WindowNodeContainer::GetNextFocusableWindow(uint32_t windowId) const
1794 {
1795     sptr<WindowNode> nextFocusableWindow;
1796     bool previousFocusedWindowFound = false;
1797     WindowNodeOperationFunc func = [windowId, &nextFocusableWindow, &previousFocusedWindowFound](
1798         sptr<WindowNode> node) {
1799         if (previousFocusedWindowFound && node->GetWindowProperty()->GetFocusable() && node->currentVisibility_) {
1800             nextFocusableWindow = node;
1801             return true;
1802         }
1803         if (node->GetWindowId() == windowId) {
1804             previousFocusedWindowFound = true;
1805         }
1806         return false;
1807     };
1808     TraverseWindowTree(func, true);
1809     return nextFocusableWindow;
1810 }
1811 
GetNextRotatableWindow(uint32_t windowId) const1812 sptr<WindowNode> WindowNodeContainer::GetNextRotatableWindow(uint32_t windowId) const
1813 {
1814     sptr<WindowNode> nextRotatableWindow;
1815     WindowNodeOperationFunc func = [windowId, &nextRotatableWindow](
1816         sptr<WindowNode> node) {
1817         if (windowId != node->GetWindowId() &&
1818             WindowHelper::IsRotatableWindow(node->GetWindowType(), node->GetWindowMode())) {
1819             nextRotatableWindow = node;
1820             return true;
1821         }
1822         return false;
1823     };
1824     TraverseWindowTree(func, true);
1825     return nextRotatableWindow;
1826 }
1827 
GetNextActiveWindow(uint32_t windowId) const1828 sptr<WindowNode> WindowNodeContainer::GetNextActiveWindow(uint32_t windowId) const
1829 {
1830     auto currentNode = FindWindowNodeById(windowId);
1831     if (currentNode == nullptr) {
1832         WLOGFE("cannot find window id: %{public}u by tree", windowId);
1833         return nullptr;
1834     }
1835     WLOGFD("current window: [%{public}u, %{public}u]", windowId, static_cast<uint32_t>(currentNode->GetWindowType()));
1836     if (WindowHelper::IsSystemWindow(currentNode->GetWindowType())) {
1837         for (auto& node : appWindowNode_->children_) {
1838             if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
1839                 continue;
1840             }
1841             return node;
1842         }
1843         for (auto& node : belowAppWindowNode_->children_) {
1844             if (node->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP) {
1845                 return node;
1846             }
1847         }
1848     } else if (WindowHelper::IsAppWindow(currentNode->GetWindowType())) {
1849         std::vector<sptr<WindowNode>> windowNodes;
1850         TraverseContainer(windowNodes);
1851         auto iter = std::find_if(windowNodes.begin(), windowNodes.end(), [windowId](sptr<WindowNode>& node) {
1852             return node->GetWindowId() == windowId;
1853             });
1854         if (iter == windowNodes.end()) {
1855             WLOGFE("could not find this window");
1856             return nullptr;
1857         }
1858         int index = std::distance(windowNodes.begin(), iter);
1859         for (size_t i = static_cast<size_t>(index) + 1; i < windowNodes.size(); i++) {
1860             if (windowNodes[i]->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE
1861                 || !windowNodes[i]->currentVisibility_) {
1862                 continue;
1863             }
1864             return windowNodes[i];
1865         }
1866     } else {
1867         // do nothing
1868     }
1869     WLOGFE("could not get next active window");
1870     return nullptr;
1871 }
1872 
IsForbidDockSliceMove(DisplayId displayId) const1873 bool WindowNodeContainer::IsForbidDockSliceMove(DisplayId displayId) const
1874 {
1875     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId);
1876     if (windowPair == nullptr) {
1877         WLOGFE("window pair is nullptr");
1878         return true;
1879     }
1880     if (windowPair->IsForbidDockSliceMove()) {
1881         return true;
1882     }
1883     return false;
1884 }
1885 
IsDockSliceInExitSplitModeArea(DisplayId displayId) const1886 bool WindowNodeContainer::IsDockSliceInExitSplitModeArea(DisplayId displayId) const
1887 {
1888     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId);
1889     if (windowPair == nullptr) {
1890         WLOGFE("window pair is nullptr");
1891         return false;
1892     }
1893     std::vector<int32_t> exitSplitPoints = windowPair->GetExitSplitPoints();
1894     if (exitSplitPoints.size() != EXIT_SPLIT_POINTS_NUMBER) {
1895         return false;
1896     }
1897     return windowPair->IsDockSliceInExitSplitModeArea(exitSplitPoints);
1898 }
1899 
ExitSplitMode(DisplayId displayId)1900 void WindowNodeContainer::ExitSplitMode(DisplayId displayId)
1901 {
1902     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId);
1903     if (windowPair == nullptr) {
1904         WLOGFE("window pair is nullptr");
1905         return;
1906     }
1907     windowPair->ExitSplitMode();
1908 }
1909 
MinimizeAllAppWindows(DisplayId displayId)1910 void WindowNodeContainer::MinimizeAllAppWindows(DisplayId displayId)
1911 {
1912     WMError ret = MinimizeAppNodeExceptOptions(MinimizeReason::MINIMIZE_ALL);
1913     SwitchLayoutPolicy(WindowLayoutMode::CASCADE, displayId);
1914     if (ret != WMError::WM_OK) {
1915         WLOGFE("Minimize all app window failed");
1916     }
1917     return;
1918 }
1919 
GetDeskTopWindow()1920 sptr<WindowNode> WindowNodeContainer::GetDeskTopWindow()
1921 {
1922     sptr<WindowNode> deskTop;
1923     WindowNodeOperationFunc findDeskTopFunc = [this, &deskTop](sptr<WindowNode> node) {
1924         if (node->GetWindowProperty()->GetWindowType() == WindowType::WINDOW_TYPE_DESKTOP) {
1925             deskTop = node;
1926             return true;
1927         }
1928         return false;
1929     };
1930     TraverseWindowTree(findDeskTopFunc, false);
1931     return deskTop;
1932 }
1933 
HasPrivateWindow()1934 bool WindowNodeContainer::HasPrivateWindow()
1935 {
1936     std::vector<sptr<WindowNode>> windowNodes;
1937     TraverseContainer(windowNodes);
1938     for (const auto& node : windowNodes) {
1939         if (node->isVisible_ && node->GetWindowProperty()->GetPrivacyMode() &&
1940         !node->GetWindowProperty()->GetOnlySkipSnapshot()) {
1941             WLOGI("window name %{public}s", node->GetWindowName().c_str());
1942             return true;
1943         }
1944     }
1945     return false;
1946 }
1947 
HasMainFullScreenWindowShown()1948 bool WindowNodeContainer::HasMainFullScreenWindowShown()
1949 {
1950     std::vector<sptr<WindowNode>> windowNodes;
1951     for (auto& node : appWindowNode_->children_) {
1952         TraverseWindowNode(node, windowNodes);
1953     }
1954     for (const auto& node : windowNodes) {
1955         if (node->currentVisibility_ &&
1956             WindowHelper::IsMainFullScreenWindow(node->GetWindowType(), node->GetWindowMode())) {
1957             return true;
1958         }
1959     }
1960     return false;
1961 }
1962 
MinimizeOldestAppWindow()1963 void WindowNodeContainer::MinimizeOldestAppWindow()
1964 {
1965     for (auto& appNode : appWindowNode_->children_) {
1966         if (appNode->GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) {
1967             MinimizeApp::AddNeedMinimizeApp(appNode, MinimizeReason::MAX_APP_COUNT);
1968             return;
1969         }
1970     }
1971     for (auto& appNode : aboveAppWindowNode_->children_) {
1972         if (appNode->GetWindowType() == WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) {
1973             MinimizeApp::AddNeedMinimizeApp(appNode, MinimizeReason::MAX_APP_COUNT);
1974             return;
1975         }
1976     }
1977     WLOGD("no window needs to minimize");
1978 }
1979 
MinimizeOldestMainFloatingWindow(uint32_t windowId)1980 void WindowNodeContainer::MinimizeOldestMainFloatingWindow(uint32_t windowId)
1981 {
1982     if (maxMainFloatingWindowNumber_ <= 0) {
1983         WLOGD("There is no limit at The number of floating window");
1984         return;
1985     }
1986 
1987     auto windowNumber = GetMainFloatingWindowCount();
1988     if (windowNumber <= maxMainFloatingWindowNumber_) {
1989         WLOGD("The number of floating window is less then MaxFloatAppMainWindowNumber");
1990         return;
1991     }
1992     std::vector<sptr<WindowNode>> rootNodes = {
1993         appWindowNode_, aboveAppWindowNode_,
1994     };
1995     for (auto& root : rootNodes) {
1996         for (auto& appNode : root->children_) {
1997             WindowType windowType = appNode->GetWindowType();
1998             WindowMode windowMode = appNode->GetWindowMode();
1999             uint32_t winId = appNode->GetWindowId();
2000             if (windowId != winId && WindowHelper::IsMainFloatingWindow(windowType, windowMode)) {
2001                 MinimizeApp::AddNeedMinimizeApp(appNode, MinimizeReason::MAX_APP_COUNT);
2002                 return;
2003             }
2004         }
2005     }
2006     WLOGD("no window needs to minimize");
2007 }
2008 
ToggleShownStateForAllAppWindows(std::function<bool (uint32_t,WindowMode)> restoreFunc,bool restore)2009 WMError WindowNodeContainer::ToggleShownStateForAllAppWindows(
2010     std::function<bool(uint32_t, WindowMode)> restoreFunc, bool restore)
2011 {
2012     for (auto node : aboveAppWindowNode_->children_) {
2013         if (node->GetWindowType() == WindowType::WINDOW_TYPE_LAUNCHER_RECENT &&
2014             node->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN && restore) {
2015             return WMError::WM_DO_NOTHING;
2016         }
2017     }
2018     // to do, backup reentry: 1.ToggleShownStateForAllAppWindows fast; 2.this display should reset backupWindowIds_.
2019     if (!restore && appWindowNode_->children_.empty() && !backupWindowIds_.empty()) {
2020         backupWindowIds_.clear();
2021         backupWindowMode_.clear();
2022         backupDisplaySplitWindowMode_.clear();
2023         backupDividerWindowRect_.clear();
2024     }
2025     if (!restore && !appWindowNode_->children_.empty() && backupWindowIds_.empty()) {
2026         WLOGD("backup");
2027         BackUpAllAppWindows();
2028     } else if (restore && !backupWindowIds_.empty()) {
2029         WLOGD("restore");
2030         RestoreAllAppWindows(restoreFunc);
2031     } else {
2032         WLOGD("do nothing because shown app windows is empty or backup windows is empty.");
2033     }
2034     WLOGD("ToggleShownStateForAllAppWindows");
2035     return WMError::WM_OK;
2036 }
2037 
BackUpAllAppWindows()2038 void WindowNodeContainer::BackUpAllAppWindows()
2039 {
2040     std::set<DisplayId> displayIdSet;
2041     backupWindowMode_.clear();
2042     backupDisplaySplitWindowMode_.clear();
2043     std::vector<sptr<WindowNode>> children = appWindowNode_->children_;
2044     for (auto& appNode : children) {
2045         if (!WindowHelper::IsMainWindow(appNode->GetWindowType())) {
2046             continue;
2047         }
2048         auto windowMode = appNode->GetWindowMode();
2049         backupWindowMode_[appNode->GetWindowId()] = windowMode;
2050         if (WindowHelper::IsSplitWindowMode(windowMode)) {
2051             backupDisplaySplitWindowMode_[appNode->GetDisplayId()].insert(windowMode);
2052         }
2053         displayIdSet.insert(appNode->GetDisplayId());
2054     }
2055     for (auto& appNode : children) {
2056         // exclude exceptional window
2057         if (!WindowHelper::IsMainWindow(appNode->GetWindowType())) {
2058             WLOGFE("is not main window, windowId:%{public}u", appNode->GetWindowId());
2059             continue;
2060         }
2061         // minimize window
2062         WLOGFD("minimize window, windowId:%{public}u", appNode->GetWindowId());
2063         backupWindowIds_.emplace_back(appNode->GetWindowId());
2064         WindowManagerService::GetInstance().RemoveWindow(appNode->GetWindowId(), true);
2065         wptr<IRemoteObject> abilityToken = appNode->abilityToken_;
2066         WindowInnerManager::GetInstance().PostTask([abilityToken]() {
2067             auto token = abilityToken.promote();
2068             if (token == nullptr) {
2069                 WLOGFW("Ability token is null");
2070                 return;
2071             }
2072             AAFwk::AbilityManagerClient::GetInstance()->DoAbilityBackground(token,
2073                 static_cast<uint32_t>(WindowStateChangeReason::TOGGLING));
2074         });
2075     }
2076     backupDividerWindowRect_.clear();
2077     for (auto displayId : displayIdSet) {
2078         auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId);
2079         if (windowPair == nullptr || windowPair->GetDividerWindow() == nullptr) {
2080             continue;
2081         }
2082         backupDividerWindowRect_[displayId] = windowPair->GetDividerWindow()->GetWindowRect();
2083     }
2084 }
2085 
RestoreAllAppWindows(std::function<bool (uint32_t,WindowMode)> restoreFunc)2086 void WindowNodeContainer::RestoreAllAppWindows(std::function<bool(uint32_t, WindowMode)> restoreFunc)
2087 {
2088     std::vector<uint32_t> backupWindowIds(backupWindowIds_);
2089     auto displayIds = DisplayGroupInfo::GetInstance().GetAllDisplayIds();
2090     std::vector<sptr<WindowPair>> windowPairs;
2091     for (auto displayId : displayIds) {
2092         auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId);
2093         if (windowPair != nullptr) {
2094             if (backupDisplaySplitWindowMode_[displayId].count(WindowMode::WINDOW_MODE_SPLIT_PRIMARY) > 0 &&
2095                 backupDisplaySplitWindowMode_[displayId].count(WindowMode::WINDOW_MODE_SPLIT_SECONDARY) > 0) {
2096                 windowPair->SetAllSplitAppWindowsRestoring(true);
2097             }
2098             windowPairs.emplace_back(windowPair);
2099         }
2100     }
2101     for (auto windowId: backupWindowIds) {
2102         if (!restoreFunc(windowId, backupWindowMode_[windowId])) {
2103             WLOGFE("restore %{public}u failed", windowId);
2104             continue;
2105         }
2106         WLOGFD("restore %{public}u", windowId);
2107     }
2108     for (auto windowPair : windowPairs) {
2109         windowPair->SetAllSplitAppWindowsRestoring(false);
2110     }
2111     layoutPolicy_->SetSplitDividerWindowRects(backupDividerWindowRect_);
2112     backupWindowIds_.clear();
2113     backupWindowMode_.clear();
2114     backupDividerWindowRect_.clear();
2115 }
2116 
IsAppWindowsEmpty() const2117 bool WindowNodeContainer::IsAppWindowsEmpty() const
2118 {
2119     return appWindowNode_->children_.empty();
2120 }
2121 
MinimizeAppNodeExceptOptions(MinimizeReason reason,const std::vector<uint32_t> & exceptionalIds,const std::vector<WindowMode> & exceptionalModes)2122 WMError WindowNodeContainer::MinimizeAppNodeExceptOptions(MinimizeReason reason,
2123     const std::vector<uint32_t> &exceptionalIds, const std::vector<WindowMode> &exceptionalModes)
2124 {
2125     if (appWindowNode_->children_.empty()) {
2126         return WMError::WM_OK;
2127     }
2128     for (auto& appNode : appWindowNode_->children_) {
2129         // exclude exceptional window
2130         if (std::find(exceptionalIds.begin(), exceptionalIds.end(), appNode->GetWindowId()) != exceptionalIds.end() ||
2131             std::find(exceptionalModes.begin(), exceptionalModes.end(),
2132                 appNode->GetWindowMode()) != exceptionalModes.end() ||
2133                 appNode->GetWindowType() != WindowType::WINDOW_TYPE_APP_MAIN_WINDOW) {
2134             continue;
2135         }
2136         MinimizeApp::AddNeedMinimizeApp(appNode, reason);
2137     }
2138     return WMError::WM_OK;
2139 }
2140 
MinimizeStructuredAppWindowsExceptSelf(const sptr<WindowNode> & node)2141 WMError WindowNodeContainer::MinimizeStructuredAppWindowsExceptSelf(const sptr<WindowNode>& node)
2142 {
2143     std::vector<uint32_t> exceptionalIds = { node->GetWindowId() };
2144     std::vector<WindowMode> exceptionalModes = { WindowMode::WINDOW_MODE_FLOATING, WindowMode::WINDOW_MODE_PIP };
2145     return MinimizeAppNodeExceptOptions(MinimizeReason::OTHER_WINDOW, exceptionalIds, exceptionalModes);
2146 }
2147 
SwitchLayoutPolicy(WindowLayoutMode dstMode,DisplayId displayId,bool reorder)2148 WMError WindowNodeContainer::SwitchLayoutPolicy(WindowLayoutMode dstMode, DisplayId displayId, bool reorder)
2149 {
2150     WLOGD("SwitchLayoutPolicy src: %{public}d dst: %{public}d, reorder: %{public}d, displayId: %{public}" PRIu64"",
2151         static_cast<uint32_t>(layoutMode_), static_cast<uint32_t>(dstMode), static_cast<uint32_t>(reorder), displayId);
2152     if (dstMode < WindowLayoutMode::BASE || dstMode >= WindowLayoutMode::END) {
2153         WLOGFE("invalid layout mode");
2154         return WMError::WM_ERROR_INVALID_PARAM;
2155     }
2156     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId);
2157     if (windowPair == nullptr) {
2158         WLOGFE("Window pair is nullptr");
2159         return WMError::WM_ERROR_NULLPTR;
2160     }
2161     if (layoutMode_ != dstMode) {
2162         if (layoutMode_ == WindowLayoutMode::CASCADE) {
2163             windowPair->Clear();
2164         }
2165         layoutMode_ = dstMode;
2166         layoutPolicy_ = layoutPolicies_[dstMode];
2167         layoutPolicy_->Launch();
2168         DumpScreenWindowTree();
2169     } else {
2170         WLOGI("Current layout mode is already: %{public}d", static_cast<uint32_t>(dstMode));
2171     }
2172     if (reorder) {
2173         windowPair->Clear();
2174         layoutPolicy_->Reorder();
2175         DumpScreenWindowTree();
2176     }
2177     NotifyIfSystemBarTintChanged(displayId);
2178     NotifyDockWindowStateChanged(displayId);
2179     return WMError::WM_OK;
2180 }
2181 
UpdateModeSupportInfoWhenKeyguardChange(const sptr<WindowNode> & node,bool up)2182 void WindowNodeContainer::UpdateModeSupportInfoWhenKeyguardChange(const sptr<WindowNode>& node, bool up)
2183 {
2184     if (!WindowHelper::IsWindowModeSupported(node->GetWindowProperty()->GetRequestModeSupportInfo(),
2185                                              WindowMode::WINDOW_MODE_SPLIT_PRIMARY)) {
2186         WLOGFD("window doesn't support split mode, winId: %{public}d", node->GetWindowId());
2187         return;
2188     }
2189     uint32_t modeSupportInfo;
2190     if (up) {
2191         modeSupportInfo = node->GetModeSupportInfo() & (~WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_PRIMARY);
2192     } else {
2193         modeSupportInfo = node->GetModeSupportInfo() | WindowModeSupport::WINDOW_MODE_SUPPORT_SPLIT_PRIMARY;
2194     }
2195     node->SetModeSupportInfo(modeSupportInfo);
2196     if (node->GetWindowToken() != nullptr) {
2197         node->GetWindowToken()->UpdateWindowModeSupportInfo(modeSupportInfo);
2198     }
2199 }
2200 
RaiseInputMethodWindowPriorityIfNeeded(const sptr<WindowNode> & node) const2201 void WindowNodeContainer::RaiseInputMethodWindowPriorityIfNeeded(const sptr<WindowNode>& node) const
2202 {
2203     if (node->GetWindowType() != WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT) {
2204         return;
2205     }
2206 
2207     if (isScreenLocked_) {
2208         node->priority_ = zorderPolicy_->GetWindowPriority(
2209             WindowType::WINDOW_TYPE_KEYGUARD) + 2; // 2: higher than keyguard and show when locked window
2210         WLOGD("Raise input method float window priority when screen locked.");
2211         return;
2212     }
2213 
2214     auto callingWindowId = node->GetCallingWindow();
2215     auto callingWindow = FindWindowNodeById(callingWindowId);
2216     if (callingWindowId == focusedWindow_ && callingWindow != nullptr) {
2217         auto callingWindowType = callingWindow->GetWindowType();
2218         auto callingWindowPriority = zorderPolicy_->GetWindowPriority(callingWindowType);
2219         auto inputMethodPriority = zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_INPUT_METHOD_FLOAT);
2220 
2221         node->priority_ = (inputMethodPriority < callingWindowPriority) ?
2222             (callingWindowPriority + 1) : inputMethodPriority;
2223         WLOGFD("Reset input method float window priority to %{public}d.", node->priority_);
2224         return;
2225     }
2226 
2227     auto focusWindow = FindWindowNodeById(focusedWindow_);
2228     if (focusWindow != nullptr && focusWindow->GetWindowType() == WindowType::WINDOW_TYPE_PANEL) {
2229         node->priority_ = zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_PANEL) + 1;
2230         WLOGFD("The input method float window should be higher than panel");
2231     }
2232 }
2233 
ReZOrderShowWhenLockedWindows(bool up)2234 void WindowNodeContainer::ReZOrderShowWhenLockedWindows(bool up)
2235 {
2236     WLOGD("Keyguard change %{public}u, re-zorder showWhenLocked window", up);
2237     std::vector<sptr<WindowNode>> needReZOrderNodes;
2238     auto& srcRoot = up ? appWindowNode_ : aboveAppWindowNode_;
2239     auto& dstRoot = up ? aboveAppWindowNode_ : appWindowNode_;
2240 
2241     auto dstPriority = up ? zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_KEYGUARD) + 1 :
2242         zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_APP_MAIN_WINDOW);
2243 
2244     for (auto iter = srcRoot->children_.begin(); iter != srcRoot->children_.end();) {
2245         if ((*iter)->GetWindowFlags() & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)) {
2246             needReZOrderNodes.emplace_back(*iter);
2247             iter = srcRoot->children_.erase(iter);
2248         } else {
2249             iter++;
2250         }
2251     }
2252     const int32_t floatingPriorityOffset = 1;
2253     for (auto& needReZOrderNode : needReZOrderNodes) {
2254         needReZOrderNode->priority_ = dstPriority;
2255         needReZOrderNode->parent_ = dstRoot;
2256         if (WindowHelper::IsMainFloatingWindow(needReZOrderNode->GetWindowType(),
2257             needReZOrderNode->GetWindowMode()) && isFloatWindowAboveFullWindow_) {
2258             needReZOrderNode->priority_ = dstPriority + floatingPriorityOffset;
2259         }
2260         auto parentNode = needReZOrderNode->parent_;
2261         auto position = parentNode->children_.end();
2262         for (auto iter = parentNode->children_.begin(); iter < parentNode->children_.end(); ++iter) {
2263             if ((*iter)->priority_ > needReZOrderNode->priority_) {
2264                 position = iter;
2265                 break;
2266             }
2267         }
2268 
2269         UpdateModeSupportInfoWhenKeyguardChange(needReZOrderNode, up);
2270 
2271         parentNode->children_.insert(position, needReZOrderNode);
2272         if (up && WindowHelper::IsSplitWindowMode(needReZOrderNode->GetWindowMode())) {
2273             needReZOrderNode->GetWindowProperty()->ResumeLastWindowMode();
2274             // when change mode, need to reset shadow and radius
2275             WindowSystemEffect::SetWindowEffect(needReZOrderNode);
2276             if (needReZOrderNode->GetWindowToken() != nullptr) {
2277                 needReZOrderNode->GetWindowToken()->UpdateWindowMode(needReZOrderNode->GetWindowMode());
2278             }
2279             auto windowPair = displayGroupController_->GetWindowPairByDisplayId(needReZOrderNode->GetDisplayId());
2280             if (windowPair == nullptr) {
2281                 WLOGFE("Window pair is nullptr");
2282                 return;
2283             }
2284             windowPair->UpdateIfSplitRelated(needReZOrderNode);
2285         }
2286         WLOGD("window %{public}u re-zorder when keyguard change %{public}u", needReZOrderNode->GetWindowId(), up);
2287     }
2288 }
2289 
ReZOrderShowWhenLockedWindowIfNeeded(const sptr<WindowNode> & node)2290 void WindowNodeContainer::ReZOrderShowWhenLockedWindowIfNeeded(const sptr<WindowNode>& node)
2291 {
2292     if (!(node->GetWindowFlags() & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)) ||
2293         !isScreenLocked_) {
2294         return;
2295     }
2296 
2297     ReZOrderShowWhenLockedWindows(true);
2298     WLOGI("ShowWhenLocked window %{public}u re-zorder to up", node->GetWindowId());
2299 }
2300 
RaiseShowWhenLockedWindowIfNeeded(const sptr<WindowNode> & node)2301 void WindowNodeContainer::RaiseShowWhenLockedWindowIfNeeded(const sptr<WindowNode>& node)
2302 {
2303     // if keyguard window show, raise show when locked windows
2304     if (node->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD) {
2305         ReZOrderShowWhenLockedWindows(true);
2306         return;
2307     }
2308 
2309     // if show when locked window show, raise itself when exist keyguard
2310     if (!(node->GetWindowFlags() & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED)) ||
2311         !isScreenLocked_) {
2312         return;
2313     }
2314 
2315     node->priority_ = zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_KEYGUARD) + 1;
2316     node->parent_ = aboveAppWindowNode_;
2317     if (WindowHelper::IsSplitWindowMode(node->GetWindowMode())) {
2318         node->GetWindowProperty()->ResumeLastWindowMode();
2319         // when change mode, need to reset shadow and radius
2320         WindowSystemEffect::SetWindowEffect(node);
2321         if (node->GetWindowToken() != nullptr) {
2322             node->GetWindowToken()->UpdateWindowMode(node->GetWindowMode());
2323         }
2324     }
2325     WLOGI("ShowWhenLocked window %{public}u raise itself", node->GetWindowId());
2326 }
2327 
DropShowWhenLockedWindowIfNeeded(const sptr<WindowNode> & node)2328 void WindowNodeContainer::DropShowWhenLockedWindowIfNeeded(const sptr<WindowNode>& node)
2329 {
2330     // if keyguard window hide, drop show when locked windows
2331     if (node->GetWindowType() == WindowType::WINDOW_TYPE_KEYGUARD) {
2332         ReZOrderShowWhenLockedWindows(false);
2333         AssignZOrder();
2334     }
2335 }
2336 
TraverseWindowTree(const WindowNodeOperationFunc & func,bool isFromTopToBottom) const2337 void WindowNodeContainer::TraverseWindowTree(const WindowNodeOperationFunc& func, bool isFromTopToBottom) const
2338 {
2339     std::vector<sptr<WindowNode>> rootNodes = { belowAppWindowNode_, appWindowNode_, aboveAppWindowNode_ };
2340     if (isFromTopToBottom) {
2341         std::reverse(rootNodes.begin(), rootNodes.end());
2342     }
2343 
2344     for (const auto& node : rootNodes) {
2345         if (isFromTopToBottom) {
2346             for (auto iter = node->children_.rbegin(); iter != node->children_.rend(); ++iter) {
2347                 if (TraverseFromTopToBottom(*iter, func)) {
2348                     return;
2349                 }
2350             }
2351         } else {
2352             for (auto iter = node->children_.begin(); iter != node->children_.end(); ++iter) {
2353                 if (TraverseFromBottomToTop(*iter, func)) {
2354                     return;
2355                 }
2356             }
2357         }
2358     }
2359 }
2360 
TraverseFromTopToBottom(sptr<WindowNode> node,const WindowNodeOperationFunc & func) const2361 bool WindowNodeContainer::TraverseFromTopToBottom(sptr<WindowNode> node, const WindowNodeOperationFunc& func) const
2362 {
2363     if (node == nullptr) {
2364         return false;
2365     }
2366     auto iterBegin = node->children_.rbegin();
2367     for (; iterBegin != node->children_.rend(); ++iterBegin) {
2368         if ((*iterBegin)->priority_ <= 0) {
2369             break;
2370         }
2371         if (func(*iterBegin)) {
2372             return true;
2373         }
2374     }
2375     if (func(node)) {
2376         return true;
2377     }
2378     for (; iterBegin != node->children_.rend(); ++iterBegin) {
2379         if (func(*iterBegin)) {
2380             return true;
2381         }
2382     }
2383     return false;
2384 }
2385 
TraverseFromBottomToTop(sptr<WindowNode> node,const WindowNodeOperationFunc & func) const2386 bool WindowNodeContainer::TraverseFromBottomToTop(sptr<WindowNode> node, const WindowNodeOperationFunc& func) const
2387 {
2388     if (node == nullptr) {
2389         return false;
2390     }
2391     auto iterBegin = node->children_.begin();
2392     for (; iterBegin != node->children_.end(); ++iterBegin) {
2393         if ((*iterBegin)->priority_ >= 0) {
2394             break;
2395         }
2396         if (func(*iterBegin)) {
2397             return true;
2398         }
2399     }
2400     if (func(node)) {
2401         return true;
2402     }
2403     for (; iterBegin != node->children_.end(); ++iterBegin) {
2404         if (func(*iterBegin)) {
2405             return true;
2406         }
2407     }
2408     return false;
2409 }
2410 
GetDisplayGroupRect() const2411 Rect WindowNodeContainer::GetDisplayGroupRect() const
2412 {
2413     return layoutPolicy_->GetDisplayGroupRect();
2414 }
2415 
UpdateSizeChangeReason(sptr<WindowNode> & node,WindowMode srcMode,WindowMode dstMode)2416 void WindowNodeContainer::UpdateSizeChangeReason(sptr<WindowNode>& node, WindowMode srcMode, WindowMode dstMode)
2417 {
2418     if ((srcMode == WindowMode::WINDOW_MODE_FULLSCREEN) && (dstMode == WindowMode::WINDOW_MODE_FLOATING)) {
2419         node->SetWindowSizeChangeReason(WindowSizeChangeReason::RECOVER);
2420     } else if (dstMode == WindowMode::WINDOW_MODE_FULLSCREEN) {
2421         node->SetWindowSizeChangeReason(WindowSizeChangeReason::MAXIMIZE);
2422         if (srcMode == WindowMode::WINDOW_MODE_FLOATING) {
2423             node->SetRequestRect(node->GetWindowRect());
2424         }
2425     } else if (WindowHelper::IsFullScreenWindow(srcMode) && WindowHelper::IsSplitWindowMode(dstMode)) {
2426         node->SetWindowSizeChangeReason(WindowSizeChangeReason::FULL_TO_SPLIT);
2427     } else if (WindowHelper::IsSplitWindowMode(srcMode) && WindowHelper::IsFullScreenWindow(dstMode)) {
2428         node->SetWindowSizeChangeReason(WindowSizeChangeReason::SPLIT_TO_FULL);
2429     } else {
2430         node->SetWindowSizeChangeReason(WindowSizeChangeReason::RESIZE);
2431     }
2432 }
2433 
SetWindowMode(sptr<WindowNode> & node,WindowMode dstMode)2434 WMError WindowNodeContainer::SetWindowMode(sptr<WindowNode>& node, WindowMode dstMode)
2435 {
2436     if (node == nullptr) {
2437         WLOGFE("could not find window");
2438         return WMError::WM_ERROR_NULLPTR;
2439     }
2440     WindowMode srcMode = node->GetWindowMode();
2441     if (WindowHelper::IsSplitWindowMode(dstMode) && isScreenLocked_ &&
2442         (node->GetWindowFlags() & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED))) {
2443         return WMError::WM_ERROR_INVALID_PARAM;
2444     }
2445 
2446     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(node->GetDisplayId());
2447     if (windowPair == nullptr) {
2448         WLOGFE("Window pair is nullptr");
2449         return WMError::WM_ERROR_NULLPTR;
2450     }
2451 
2452     WindowPairStatus status = windowPair->GetPairStatus();
2453     // when status is single primary or single secondary, split node is abandoned to set mode
2454     if (node->IsSplitMode() && (status == WindowPairStatus::SINGLE_PRIMARY ||
2455         status == WindowPairStatus::SINGLE_SECONDARY)) {
2456         return WMError::WM_ERROR_INVALID_OPERATION;
2457     }
2458     WMError res = WMError::WM_OK;
2459     UpdateSizeChangeReason(node, srcMode, dstMode);
2460     node->SetWindowMode(dstMode);
2461     windowPair->UpdateIfSplitRelated(node);
2462 
2463     if (WindowHelper::IsMainWindow(node->GetWindowType())) {
2464         if (WindowHelper::IsFloatingWindow(node->GetWindowMode())) {
2465             NotifyDockWindowStateChanged(node, true);
2466         } else {
2467             NotifyDockWindowStateChanged(node, false);
2468         }
2469     }
2470 
2471     if (node->GetWindowMode() == WindowMode::WINDOW_MODE_FULLSCREEN &&
2472         WindowHelper::IsAppWindow(node->GetWindowType())) {
2473         // minimize other app window.
2474         res = MinimizeStructuredAppWindowsExceptSelf(node);
2475         if (res != WMError::WM_OK) {
2476             return res;
2477         }
2478     }
2479     // when change mode, need to reset shadow and radius.
2480     WindowSystemEffect::SetWindowEffect(node);
2481 
2482     // when change mode, need to reset MainFloatingWindow ZOrder.
2483     ResetWindowZOrderPriorityWhenSetMode(node, dstMode, srcMode);
2484     MinimizeOldestMainFloatingWindow(node->GetWindowId());
2485 
2486     if (node->GetWindowToken() != nullptr) {
2487         node->GetWindowToken()->UpdateWindowMode(node->GetWindowMode());
2488     }
2489     res = UpdateWindowNode(node, WindowUpdateReason::UPDATE_MODE);
2490     if (res != WMError::WM_OK) {
2491         WLOGFE("Set window mode failed, update node failed");
2492         return res;
2493     }
2494     return WMError::WM_OK;
2495 }
2496 
ResetWindowZOrderPriorityWhenSetMode(sptr<WindowNode> & node,const WindowMode & dstMode,const WindowMode & srcMode)2497 void WindowNodeContainer::ResetWindowZOrderPriorityWhenSetMode(sptr<WindowNode>& node,
2498     const WindowMode& dstMode, const WindowMode& srcMode)
2499 {
2500     if (!isFloatWindowAboveFullWindow_) {
2501         return;
2502     }
2503 
2504     // reset node zorder priority.
2505     if (WindowHelper::IsMainFloatingWindow(node->GetWindowType(), srcMode)) {
2506         auto basePriority = zorderPolicy_->GetWindowPriority(node->GetWindowType());
2507         if (isScreenLocked_ &&
2508             (node->GetWindowFlags() & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_SHOW_WHEN_LOCKED))) {
2509             basePriority = zorderPolicy_->GetWindowPriority(WindowType::WINDOW_TYPE_KEYGUARD) + 1;
2510         }
2511         node->priority_ = basePriority;
2512     }
2513 
2514     if (!WindowHelper::IsMainFloatingWindow(node->GetWindowType(), srcMode) &&
2515         !WindowHelper::IsMainFloatingWindow(node->GetWindowType(), dstMode) &&
2516         !WindowHelper::IsSplitWindowMode(srcMode) &&
2517         !WindowHelper::IsSplitWindowMode(dstMode)) {
2518         return;
2519     }
2520 
2521     // When set mode, all floating window should be checked and raise
2522     ResetAllMainFloatingWindowZOrder(node->parent_);
2523     if (node->parent_ != nullptr && node->GetWindowId() == focusedWindow_ &&
2524         WindowHelper::IsMainFloatingWindow(node->GetWindowType(), dstMode)) {
2525         // if current node is mainFloatingWIndow and foucsedWindow, it should be raised to top.
2526         RaiseWindowToTop(node->GetWindowId(), node->parent_->children_);
2527     }
2528     AssignZOrder();
2529 }
2530 
GetModeChangeHotZones(DisplayId displayId,ModeChangeHotZones & hotZones,const ModeChangeHotZonesConfig & config)2531 void WindowNodeContainer::GetModeChangeHotZones(DisplayId displayId, ModeChangeHotZones& hotZones,
2532     const ModeChangeHotZonesConfig& config)
2533 {
2534     const auto& displayRect = DisplayGroupInfo::GetInstance().GetDisplayRect(displayId);
2535 
2536     hotZones.fullscreen_.width_ = displayRect.width_;
2537     hotZones.fullscreen_.height_ = config.fullscreenRange_;
2538 
2539     hotZones.primary_.width_ = config.primaryRange_;
2540     hotZones.primary_.height_ = displayRect.height_;
2541 
2542     hotZones.secondary_.posX_ = static_cast<int32_t>(displayRect.width_) - config.secondaryRange_;
2543     hotZones.secondary_.width_ = config.secondaryRange_;
2544     hotZones.secondary_.height_ = displayRect.height_;
2545 }
2546 
UpdateCameraFloatWindowStatus(const sptr<WindowNode> & node,bool isShowing)2547 void WindowNodeContainer::UpdateCameraFloatWindowStatus(const sptr<WindowNode>& node, bool isShowing)
2548 {
2549     if (node->GetWindowType() == WindowType::WINDOW_TYPE_FLOAT_CAMERA) {
2550         WindowManagerAgentController::GetInstance().UpdateCameraFloatWindowStatus(node->GetAccessTokenId(), isShowing);
2551     }
2552 }
2553 
GetCurrentLayoutMode() const2554 WindowLayoutMode WindowNodeContainer::GetCurrentLayoutMode() const
2555 {
2556     return layoutMode_;
2557 }
2558 
RemoveSingleUserWindowNodes(int accountId)2559 void WindowNodeContainer::RemoveSingleUserWindowNodes(int accountId)
2560 {
2561     std::vector<sptr<WindowNode>> windowNodes;
2562     TraverseContainer(windowNodes);
2563     WLOGI("%{public}d", accountId);
2564     for (auto& windowNode : windowNodes) {
2565         int windowAccountId = windowNode->GetCallingUid() / UID_TRANSFROM_DIVISOR;
2566         if (windowAccountId < UID_MIN || windowAccountId == accountId) {
2567             WLOGD("skiped window %{public}s, windowId %{public}d uid %{public}d",
2568                 windowNode->GetWindowName().c_str(), windowNode->GetWindowId(), windowNode->GetCallingUid());
2569             continue;
2570         }
2571         WLOGD("remove window %{public}s, windowId %{public}d uid %{public}d",
2572             windowNode->GetWindowName().c_str(), windowNode->GetWindowId(), windowNode->GetCallingUid());
2573         windowNode->GetWindowProperty()->SetAnimationFlag(static_cast<uint32_t>(WindowAnimation::NONE));
2574         if (windowNode->GetWindowToken()) {
2575             if (windowNode->surfaceNode_ != nullptr) {
2576                 windowNode->surfaceNode_->SetVisible(true);
2577             }
2578             windowNode->GetWindowToken()->UpdateWindowState(WindowState::STATE_HIDDEN);
2579         }
2580     }
2581 }
2582 
TakeWindowPairSnapshot(DisplayId displayId)2583 bool WindowNodeContainer::TakeWindowPairSnapshot(DisplayId displayId)
2584 {
2585     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId);
2586     return windowPair == nullptr ? false : windowPair->TakePairSnapshot();
2587 }
2588 
ClearWindowPairSnapshot(DisplayId displayId)2589 void WindowNodeContainer::ClearWindowPairSnapshot(DisplayId displayId)
2590 {
2591     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId);
2592     if (windowPair == nullptr) {
2593         WLOGFE("Window pair is nullptr");
2594         return;
2595     }
2596     windowPair->ClearPairSnapshot();
2597 }
2598 
SetWindowPairFrameGravity(DisplayId displayId,Gravity gravity)2599 void WindowNodeContainer::SetWindowPairFrameGravity(DisplayId displayId, Gravity gravity)
2600 {
2601     auto windowPair = displayGroupController_->GetWindowPairByDisplayId(displayId);
2602     if (windowPair == nullptr) {
2603         WLOGFE("Window pair is nullptr");
2604         return;
2605     }
2606     std::vector<sptr<WindowNode>> windowNodes = windowPair->GetPairedWindows();
2607     for (auto& windowNode : windowNodes) {
2608         if (windowNode->surfaceNode_) {
2609             windowNode->surfaceNode_->SetFrameGravity(gravity);
2610         }
2611     }
2612 }
2613 
IsScreenLocked()2614 bool WindowNodeContainer::IsScreenLocked()
2615 {
2616     return isScreenLocked_;
2617 }
2618 
GetAnimateTransactionEnabled()2619 bool WindowNodeContainer::GetAnimateTransactionEnabled()
2620 {
2621     return isAnimateTransactionEnabled_;
2622 }
2623 } // namespace Rosen
2624 } // namespace OHOS
2625