• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2022 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_layout_policy_tile.h"
17 #include <ability_manager_client.h>
18 #include "window_helper.h"
19 #include "window_inner_manager.h"
20 #include "window_manager_hilog.h"
21 #include "wm_trace.h"
22 
23 namespace OHOS {
24 namespace Rosen {
25 namespace {
26     constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "WindowLayoutPolicyTile"};
27     constexpr uint32_t EDGE_INTERVAL = 48;
28     constexpr uint32_t MID_INTERVAL = 24;
29 }
WindowLayoutPolicyTile(const Rect & displayRect,const uint64_t & screenId,sptr<WindowNode> & belowAppNode,sptr<WindowNode> & appNode,sptr<WindowNode> & aboveAppNode)30 WindowLayoutPolicyTile::WindowLayoutPolicyTile(const Rect& displayRect, const uint64_t& screenId,
31     sptr<WindowNode>& belowAppNode, sptr<WindowNode>& appNode, sptr<WindowNode>& aboveAppNode)
32     : WindowLayoutPolicy(displayRect, screenId, belowAppNode, appNode, aboveAppNode)
33 {
34 }
35 
Launch()36 void WindowLayoutPolicyTile::Launch()
37 {
38     // compute limit rect
39     UpdateDisplayInfo();
40     // select app min win in queue, and minimize others
41     InitForegroundNodeQueue();
42     AssignNodePropertyForTileWindows();
43     LayoutForegroundNodeQueue();
44     LayoutWindowNode(belowAppWindowNode_);
45     WLOGFI("WindowLayoutPolicyTile::Launch");
46 }
47 
UpdateDisplayInfo()48 void WindowLayoutPolicyTile::UpdateDisplayInfo()
49 {
50     limitRect_ = displayRect_;
51     LayoutWindowNode(aboveAppWindowNode_);
52     InitTileWindowRects();
53 }
54 
GetMaxTileWinNum() const55 uint32_t WindowLayoutPolicyTile::GetMaxTileWinNum() const
56 {
57     float virtualPixelRatio = GetVirtualPixelRatio();
58     constexpr uint32_t half = 2;
59     uint32_t edgeIntervalVp = static_cast<uint32_t>(EDGE_INTERVAL * half * virtualPixelRatio);
60     uint32_t midIntervalVp = static_cast<uint32_t>(MID_INTERVAL * virtualPixelRatio);
61     uint32_t minFloatingW = IsVertical() ? MIN_VERTICAL_FLOATING_WIDTH : MIN_VERTICAL_FLOATING_HEIGHT;
62     minFloatingW = static_cast<uint32_t>(minFloatingW * virtualPixelRatio);
63     uint32_t drawableW = limitRect_.width_ - edgeIntervalVp + midIntervalVp;
64     return static_cast<uint32_t>(drawableW / (minFloatingW + midIntervalVp));
65 }
66 
InitTileWindowRects()67 void WindowLayoutPolicyTile::InitTileWindowRects()
68 {
69     float virtualPixelRatio = GetVirtualPixelRatio();
70     uint32_t edgeIntervalVp = static_cast<uint32_t>(EDGE_INTERVAL * virtualPixelRatio);
71     uint32_t midIntervalVp = static_cast<uint32_t>(MID_INTERVAL * virtualPixelRatio);
72 
73     constexpr float ratio = 0.75;  // 0.75: default height/width ratio
74     constexpr float edgeRatio = 0.125;
75     constexpr int half = 2;
76     maxTileWinNum_ = GetMaxTileWinNum();
77     WLOGFI("set max tile window num %{public}u", maxTileWinNum_);
78     presetRects_.clear();
79     int x = limitRect_.posX_ + (limitRect_.width_ * edgeRatio);
80     int y = limitRect_.posY_ + (limitRect_.height_ * edgeRatio);
81     uint32_t w = limitRect_.width_ * ratio;
82     uint32_t h = limitRect_.height_ * ratio;
83     std::vector<Rect> single = {{ x, y, w, h }};
84     presetRects_.emplace_back(single);
85     for (uint32_t num = 2; num <= maxTileWinNum_; num++) { // start calc preset with 2 windows
86         w = (limitRect_.width_ - edgeIntervalVp * half - midIntervalVp * (num - 1)) / num;
87         std::vector<Rect> curLevel;
88         for (uint32_t i = 0; i < num; i++) {
89             int curX = limitRect_.posX_ + edgeIntervalVp + i * (w + midIntervalVp);
90             Rect curRect = { curX, y, w, h };
91             WLOGFI("presetRects: level %{public}d, id %{public}d, [%{public}d %{public}d %{public}d %{public}d]",
92                 num, i, curX, y, w, h);
93             curLevel.emplace_back(curRect);
94         }
95         presetRects_.emplace_back(curLevel);
96     }
97 }
98 
AddWindowNode(sptr<WindowNode> & node)99 void WindowLayoutPolicyTile::AddWindowNode(sptr<WindowNode>& node)
100 {
101     WM_FUNCTION_TRACE();
102     if (WindowHelper::IsMainWindow(node->GetWindowType())) {
103         ForegroundNodeQueuePushBack(node);
104         AssignNodePropertyForTileWindows();
105         LayoutForegroundNodeQueue();
106     } else {
107         UpdateWindowNode(node); // currently, update and add do the same process
108     }
109 }
110 
UpdateWindowNode(sptr<WindowNode> & node,bool isAddWindow)111 void WindowLayoutPolicyTile::UpdateWindowNode(sptr<WindowNode>& node, bool isAddWindow)
112 {
113     WM_FUNCTION_TRACE();
114     WindowLayoutPolicy::UpdateWindowNode(node);
115     if (avoidTypes_.find(node->GetWindowType()) != avoidTypes_.end()) {
116         InitTileWindowRects();
117         AssignNodePropertyForTileWindows();
118         LayoutForegroundNodeQueue();
119     }
120 }
121 
RemoveWindowNode(sptr<WindowNode> & node)122 void WindowLayoutPolicyTile::RemoveWindowNode(sptr<WindowNode>& node)
123 {
124     WM_FUNCTION_TRACE();
125     WLOGFI("RemoveWindowNode %{public}d in tile", node->GetWindowId());
126     auto type = node->GetWindowType();
127     // affect other windows, trigger off global layout
128     if (avoidTypes_.find(type) != avoidTypes_.end()) {
129         LayoutWindowTree();
130     } else {
131         ForegroundNodeQueueRemove(node);
132         AssignNodePropertyForTileWindows();
133         LayoutForegroundNodeQueue();
134     }
135     Rect winRect = node->GetWindowProperty()->GetWindowRect();
136     node->GetWindowToken()->UpdateWindowRect(winRect, WindowSizeChangeReason::HIDE);
137 }
138 
LayoutForegroundNodeQueue()139 void WindowLayoutPolicyTile::LayoutForegroundNodeQueue()
140 {
141     for (auto& node : foregroundNodes_) {
142         Rect lastRect = node->GetLayoutRect();
143         Rect winRect = node->GetWindowProperty()->GetWindowRect();
144         node->SetLayoutRect(winRect);
145         CalcAndSetNodeHotZone(winRect, node);
146         if (!(lastRect == winRect)) {
147             node->GetWindowToken()->UpdateWindowRect(winRect, node->GetWindowSizeChangeReason());
148             node->surfaceNode_->SetBounds(winRect.posX_, winRect.posY_, winRect.width_, winRect.height_);
149         }
150         for (auto& childNode : node->children_) {
151             LayoutWindowNode(childNode);
152         }
153     }
154 }
155 
InitForegroundNodeQueue()156 void WindowLayoutPolicyTile::InitForegroundNodeQueue()
157 {
158     foregroundNodes_.clear();
159     for (auto& node : appWindowNode_->children_) {
160         if (WindowHelper::IsMainWindow(node->GetWindowType())) {
161             ForegroundNodeQueuePushBack(node);
162         }
163     }
164 }
165 
ForegroundNodeQueuePushBack(sptr<WindowNode> & node)166 void WindowLayoutPolicyTile::ForegroundNodeQueuePushBack(sptr<WindowNode>& node)
167 {
168     if (node == nullptr) {
169         return;
170     }
171     WLOGFI("add win in tile for win id: %{public}d", node->GetWindowId());
172     while (foregroundNodes_.size() >= maxTileWinNum_) {
173         auto removeNode = foregroundNodes_.front();
174         foregroundNodes_.pop_front();
175         WLOGFI("pop win in queue head id: %{public}d, for add new win", removeNode->GetWindowId());
176         if (removeNode->abilityToken_ != nullptr) {
177             WLOGFI("minimize win %{public}d in tile", removeNode->GetWindowId());
178             AAFwk::AbilityManagerClient::GetInstance()->MinimizeAbility(removeNode->abilityToken_);
179         }
180     }
181     foregroundNodes_.push_back(node);
182 }
183 
ForegroundNodeQueueRemove(sptr<WindowNode> & node)184 void WindowLayoutPolicyTile::ForegroundNodeQueueRemove(sptr<WindowNode>& node)
185 {
186     if (node == nullptr) {
187         return;
188     }
189     auto iter = std::find(foregroundNodes_.begin(), foregroundNodes_.end(), node);
190     if (iter != foregroundNodes_.end()) {
191         WLOGFI("remove win in tile for win id: %{public}d", node->GetWindowId());
192         foregroundNodes_.erase(iter);
193     }
194 }
195 
AssignNodePropertyForTileWindows()196 void WindowLayoutPolicyTile::AssignNodePropertyForTileWindows()
197 {
198     // set rect for foreground windows
199     uint32_t num = foregroundNodes_.size();
200     if (num > maxTileWinNum_ || num > presetRects_.size() || num == 0) {
201         WLOGE("invalid tile queue");
202         return;
203     }
204     std::vector<Rect>& presetRect = presetRects_[num - 1];
205     if (presetRect.size() != num) {
206         WLOGE("invalid preset rects");
207         return;
208     }
209     auto rectIt = presetRect.begin();
210     for (auto node : foregroundNodes_) {
211         auto& rect = (*rectIt);
212         node->SetWindowMode(WindowMode::WINDOW_MODE_FLOATING);
213         node->GetWindowToken()->UpdateWindowMode(WindowMode::WINDOW_MODE_FLOATING);
214         node->SetWindowRect(rect);
215         node->hasDecorated_ = true;
216         WLOGFI("set rect for qwin id: %{public}d [%{public}d %{public}d %{public}d %{public}d]",
217             node->GetWindowId(), rect.posX_, rect.posY_, rect.width_, rect.height_);
218         rectIt++;
219     }
220 }
221 
UpdateLayoutRect(sptr<WindowNode> & node)222 void WindowLayoutPolicyTile::UpdateLayoutRect(sptr<WindowNode>& node)
223 {
224     auto type = node->GetWindowType();
225     auto mode = node->GetWindowMode();
226     auto flags = node->GetWindowFlags();
227     auto decorEnbale = node->GetWindowProperty()->GetDecorEnable();
228     bool needAvoid = (flags & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_NEED_AVOID));
229     bool parentLimit = (flags & static_cast<uint32_t>(WindowFlag::WINDOW_FLAG_PARENT_LIMIT));
230     bool subWindow = WindowHelper::IsSubWindow(type);
231     bool floatingWindow = (mode == WindowMode::WINDOW_MODE_FLOATING);
232     const Rect& layoutRect = node->GetLayoutRect();
233     Rect lastRect = layoutRect;
234     Rect displayRect = displayRect_;
235     Rect limitRect = displayRect;
236     Rect winRect = node->GetWindowProperty()->GetWindowRect();
237 
238     WLOGFI("Id:%{public}d, avoid:%{public}d parLimit:%{public}d floating:%{public}d, sub:%{public}d, " \
239         "deco:%{public}d, type:%{public}d, requestRect:[%{public}d, %{public}d, %{public}d, %{public}d]",
240         node->GetWindowId(), needAvoid, parentLimit, floatingWindow, subWindow, decorEnbale,
241         static_cast<uint32_t>(type), winRect.posX_, winRect.posY_, winRect.width_, winRect.height_);
242     if (needAvoid) {
243         limitRect = limitRect_;
244     }
245 
246     if (!floatingWindow) { // fullscreen window
247         winRect = limitRect;
248     } else { // floating window
249         if (node->GetWindowProperty()->GetDecorEnable()) { // is decorable
250             winRect = ComputeDecoratedWindowRect(winRect);
251         }
252         if (subWindow && parentLimit) { // subwidow and limited by parent
253             limitRect = node->parent_->GetLayoutRect();
254             UpdateFloatingLayoutRect(limitRect, winRect);
255         }
256     }
257     LimitWindowSize(node, displayRect, winRect);
258     node->SetLayoutRect(winRect);
259     CalcAndSetNodeHotZone(winRect, node);
260     if (!(lastRect == winRect)) {
261         auto reason = node->GetWindowSizeChangeReason();
262         node->GetWindowToken()->UpdateWindowRect(winRect, reason);
263         if (reason == WindowSizeChangeReason::DRAG || reason == WindowSizeChangeReason::DRAG_END) {
264             node->ResetWindowSizeChangeReason();
265         }
266     }
267     // update node bounds
268     if (node->surfaceNode_ != nullptr) {
269         node->surfaceNode_->SetBounds(winRect.posX_, winRect.posY_, winRect.width_, winRect.height_);
270     }
271 }
272 } // Rosen
273 } // OHOS