1 /*
2 * Copyright (c) 2025 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 "session/host/include/layout_controller.h"
17
18 #include <cinttypes>
19 #include <transaction/rs_transaction.h>
20 #include <ui/rs_surface_node.h>
21
22 #include "display_manager.h"
23 #include "screen_session_manager_client/include/screen_session_manager_client.h"
24 #include "session/host/include/scene_persistent_storage.h"
25 #include "session/host/include/scene_session.h"
26 #include "session/host/include/session_utils.h"
27 #include "session_helper.h"
28 #include "window_helper.h"
29 #include "window_manager_hilog.h"
30 #include "wm_common_inner.h"
31
32 namespace OHOS::Rosen {
33 namespace {
34 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "LayoutController"};
35 }
36
LayoutController(const sptr<WindowSessionProperty> & property)37 LayoutController::LayoutController(const sptr<WindowSessionProperty>& property)
38 {
39 sessionProperty_ = property;
40 }
41
42 // LCOV_EXCL_START
SetSessionGlobalRect(const WSRect & rect)43 bool LayoutController::SetSessionGlobalRect(const WSRect& rect)
44 {
45 std::lock_guard<std::mutex> lock(globalRectMutex_);
46 if (globalRect_ == rect) {
47 return false;
48 }
49 globalRect_ = rect;
50 return true;
51 }
52 // LCOV_EXCL_STOP
53
GetSessionGlobalRect() const54 WSRect LayoutController::GetSessionGlobalRect() const
55 {
56 if (Session::IsScbCoreEnabled()) {
57 std::lock_guard<std::mutex> lock(globalRectMutex_);
58 return globalRect_;
59 }
60 return winRect_;
61 }
62
SetClientRect(const WSRect & rect)63 void LayoutController::SetClientRect(const WSRect& rect)
64 {
65 if (clientRect_ == rect) {
66 TLOGD(WmsLogTag::WMS_LAYOUT, "id:%{public}d skip same rect", GetSessionPersistentId());
67 return;
68 }
69 clientRect_ = rect;
70 TLOGD(WmsLogTag::WMS_LAYOUT, "Id:%{public}d, update client rect:%{public}s",
71 GetSessionPersistentId(), rect.ToString().c_str());
72 }
73
GetClientRect() const74 WSRect LayoutController::GetClientRect() const
75 {
76 return clientRect_;
77 }
78
GetGlobalScaledRect(Rect & globalScaledRect)79 void LayoutController::GetGlobalScaledRect(Rect& globalScaledRect)
80 {
81 WSRect scaledRect = GetSessionGlobalRect();
82 scaledRect.width_ *= GetScaleX();
83 scaledRect.height_ *= GetScaleY();
84 globalScaledRect = { scaledRect.posX_, scaledRect.posY_, scaledRect.width_, scaledRect.height_ };
85 }
86
87 // LCOV_EXCL_START
ConvertRelativeRectToGlobal(const WSRect & relativeRect,DisplayId currentDisplayId) const88 WSRect LayoutController::ConvertRelativeRectToGlobal(const WSRect& relativeRect, DisplayId currentDisplayId) const
89 {
90 sptr<ScreenSession> screenSession =
91 ScreenSessionManagerClient::GetInstance().GetScreenSessionById(currentDisplayId);
92 if (!screenSession) {
93 TLOGW(WmsLogTag::WMS_LAYOUT, "Screen session is null, displayId:%{public}" PRIu64, currentDisplayId);
94 screenSession =
95 ScreenSessionManagerClient::GetInstance().GetScreenSessionById(sessionProperty_->GetDisplayId());
96 if (!screenSession) {
97 TLOGW(WmsLogTag::WMS_LAYOUT, "Screen session is null, displayId:%{public}" PRIu64,
98 sessionProperty_->GetDisplayId());
99 return relativeRect;
100 }
101 }
102 const ScreenProperty& screenProperty = screenSession->GetScreenProperty();
103 int32_t currentDisplayOffsetX = static_cast<int32_t>(screenProperty.GetStartX());
104 int32_t currentDisplayOffsetY = static_cast<int32_t>(screenProperty.GetStartY());
105 TLOGI(WmsLogTag::WMS_LAYOUT, "id:%{public}d, relativeRect:%{public}s, offsetX:%{public}d, offsetY:%{public}d",
106 GetSessionPersistentId(), relativeRect.ToString().c_str(), currentDisplayOffsetX, currentDisplayOffsetY);
107 return {relativeRect.posX_ + currentDisplayOffsetX,
108 relativeRect.posY_ + currentDisplayOffsetY,
109 relativeRect.width_, relativeRect.height_};
110 }
111
ConvertGlobalRectToRelative(const WSRect & globalRect,DisplayId targetDisplayId) const112 WSRect LayoutController::ConvertGlobalRectToRelative(const WSRect& globalRect, DisplayId targetDisplayId) const
113 {
114 sptr<ScreenSession> screenSession =
115 ScreenSessionManagerClient::GetInstance().GetScreenSessionById(targetDisplayId);
116 if (!screenSession) {
117 TLOGW(WmsLogTag::WMS_LAYOUT, "Screen session is null, displayId:%{public}" PRIu64, targetDisplayId);
118 screenSession =
119 ScreenSessionManagerClient::GetInstance().GetScreenSessionById(sessionProperty_->GetDisplayId());
120 if (!screenSession) {
121 TLOGW(WmsLogTag::WMS_LAYOUT, "Screen session is null, displayId:%{public}" PRIu64,
122 sessionProperty_->GetDisplayId());
123 return globalRect;
124 }
125 }
126 const ScreenProperty& screenProperty = screenSession->GetScreenProperty();
127 int32_t targetDisplayOffsetX = static_cast<int32_t>(screenProperty.GetStartX());
128 int32_t targetDisplayOffsetY = static_cast<int32_t>(screenProperty.GetStartY());
129 TLOGI(WmsLogTag::WMS_LAYOUT, "id:%{public}d, globalRect:%{public}s, offsetX:%{public}d, offsetY:%{public}d",
130 GetSessionPersistentId(), globalRect.ToString().c_str(), targetDisplayOffsetX, targetDisplayOffsetY);
131 return {globalRect.posX_ - targetDisplayOffsetX,
132 globalRect.posY_ - targetDisplayOffsetY,
133 globalRect.width_, globalRect.height_};
134 }
135
GetSessionPersistentId() const136 int32_t LayoutController::GetSessionPersistentId() const
137 {
138 return sessionProperty_->GetPersistentId();
139 }
140
AdjustRectByLimits(WindowLimits limits,float ratio,bool isDecor,float vpr,WSRect & rect)141 void LayoutController::AdjustRectByLimits(WindowLimits limits, float ratio, bool isDecor, float vpr, WSRect& rect)
142 {
143 if (isDecor) {
144 rect.width_ = SessionUtils::ToLayoutWidth(rect.width_, vpr);
145 rect.height_ = SessionUtils::ToLayoutHeight(rect.height_, vpr);
146 limits.minWidth_ = SessionUtils::ToLayoutWidth(limits.minWidth_, vpr);
147 limits.maxWidth_ = SessionUtils::ToLayoutWidth(limits.maxWidth_, vpr);
148 limits.minHeight_ = SessionUtils::ToLayoutHeight(limits.minHeight_, vpr);
149 limits.maxHeight_ = SessionUtils::ToLayoutHeight(limits.maxHeight_, vpr);
150 }
151 if (static_cast<uint32_t>(rect.height_) > limits.maxHeight_) {
152 rect.height_ = static_cast<int32_t>(limits.maxHeight_);
153 rect.width_ = floor(rect.height_ * ratio);
154 } else if (static_cast<uint32_t>(rect.width_) > limits.maxWidth_) {
155 rect.width_ = static_cast<int32_t>(limits.maxWidth_);
156 rect.height_ = floor(rect.width_ / ratio);
157 } else if (static_cast<uint32_t>(rect.width_) < limits.minWidth_) {
158 rect.width_ = static_cast<int32_t>(limits.minWidth_);
159 rect.height_ = ceil(rect.width_ / ratio);
160 } else if (static_cast<uint32_t>(rect.height_) < limits.minHeight_) {
161 rect.height_ = static_cast<int32_t>(limits.minHeight_);
162 rect.width_ = ceil(rect.height_ * ratio);
163 }
164 if (isDecor) {
165 rect.height_ = SessionUtils::ToWinHeight(rect.height_, vpr) ;
166 rect.width_ = SessionUtils::ToWinWidth(rect.width_, vpr);
167 }
168 }
169
AdjustRectByAspectRatio(WSRect & rect,bool isDecorEnable)170 bool LayoutController::AdjustRectByAspectRatio(WSRect& rect, bool isDecorEnable)
171 {
172 const int tolerancePx = 2; // 2: tolerance delta pixel value, unit: px
173 WSRect originalRect = rect;
174 if (sessionProperty_->GetWindowMode() != WindowMode::WINDOW_MODE_FLOATING ||
175 !WindowHelper::IsMainWindow(sessionProperty_->GetWindowType())) {
176 return false;
177 }
178
179 if (MathHelper::NearZero(aspectRatio_)) {
180 return false;
181 }
182 float vpr = 1.5f; // 1.5f: default virtual pixel ratio
183 auto display = DisplayManager::GetInstance().GetDefaultDisplay();
184 if (display) {
185 vpr = display->GetVirtualPixelRatio();
186 }
187 int32_t minW;
188 int32_t maxW;
189 int32_t minH;
190 int32_t maxH;
191 SessionUtils::CalcFloatWindowRectLimits(sessionProperty_->GetWindowLimits(),
192 getSystemConfigFunc_().maxFloatingWindowSize_, vpr, minW, maxW, minH, maxH);
193 rect.width_ = std::max(minW, static_cast<int32_t>(rect.width_));
194 rect.width_ = std::min(maxW, static_cast<int32_t>(rect.width_));
195 rect.height_ = std::max(minH, static_cast<int32_t>(rect.height_));
196 rect.height_ = std::min(maxH, static_cast<int32_t>(rect.height_));
197 if (isDecorEnable) {
198 if (SessionUtils::ToLayoutWidth(rect.width_, vpr) >
199 SessionUtils::ToLayoutHeight(rect.height_, vpr) * aspectRatio_) {
200 rect.width_ = SessionUtils::ToWinWidth(SessionUtils::ToLayoutHeight(rect.height_, vpr)* aspectRatio_, vpr);
201 } else {
202 rect.height_ = SessionUtils::ToWinHeight(SessionUtils::ToLayoutWidth(rect.width_, vpr) / aspectRatio_, vpr);
203 }
204 } else {
205 if (rect.width_ > rect.height_ * aspectRatio_) {
206 rect.width_ = rect.height_ * aspectRatio_;
207 } else {
208 rect.height_ = rect.width_ / aspectRatio_;
209 }
210 }
211 AdjustRectByLimits(sessionProperty_->GetWindowLimits(), aspectRatio_, isDecorEnable, vpr, rect);
212 if (std::abs(static_cast<int32_t>(originalRect.width_) - static_cast<int32_t>(rect.width_)) <= tolerancePx &&
213 std::abs(static_cast<int32_t>(originalRect.height_) - static_cast<int32_t>(rect.height_)) <= tolerancePx) {
214 rect = originalRect;
215 return false;
216 }
217 return true;
218 }
219
SetScale(float scaleX,float scaleY,float pivotX,float pivotY)220 void LayoutController::SetScale(float scaleX, float scaleY, float pivotX, float pivotY)
221 {
222 scaleX_ = scaleX;
223 scaleY_ = scaleY;
224 pivotX_ = pivotX;
225 pivotY_ = pivotY;
226 }
227
SetClientScale(float scaleX,float scaleY,float pivotX,float pivotY)228 void LayoutController::SetClientScale(float scaleX, float scaleY, float pivotX, float pivotY)
229 {
230 TLOGD(WmsLogTag::WMS_LAYOUT, "Id:%{public}d, preScaleX:%{public}f, preScaleY:%{public}f, "
231 "newScaleX:%{public}f, newScaleY:%{public}f", GetSessionPersistentId(),
232 clientScaleX_, clientScaleY_, scaleX, scaleY);
233 clientScaleX_ = scaleX;
234 clientScaleY_ = scaleY;
235 clientPivotX_ = pivotX;
236 clientPivotY_ = pivotY;
237 }
238
IsTransformNeedUpdate(float scaleX,float scaleY,float pivotX,float pivotY)239 bool LayoutController::IsTransformNeedUpdate(float scaleX, float scaleY, float pivotX, float pivotY)
240 {
241 bool nearEqual = NearEqual(scaleX_, scaleX) && NearEqual(scaleY_, scaleY) &&
242 NearEqual(pivotX_, pivotX) && NearEqual(pivotY_, pivotY) &&
243 NearEqual(clientScaleX_, scaleX) && NearEqual(clientScaleY_, scaleY) &&
244 NearEqual(clientPivotX_, pivotX) && NearEqual(clientPivotY_, pivotY);
245 return !nearEqual;
246 }
247 // LCOV_EXCL_STOP
248
SetSystemConfigFunc(GetSystemConfigFunc && func)249 void LayoutController::SetSystemConfigFunc(GetSystemConfigFunc&& func)
250 {
251 if (!func) {
252 TLOGW(WmsLogTag::WMS_LAYOUT, "func is null");
253 return;
254 }
255 getSystemConfigFunc_ = std::move(func);
256 }
257
258 } // namespace OHOS::Rosen
259