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 "screen_cutout_controller.h"
17
18 #include "screen_scene_config.h"
19 #include "screen_session_manager.h"
20 #include "window_manager_hilog.h"
21
22 namespace OHOS::Rosen {
23 namespace {
24 constexpr std::vector<int>::size_type LEFT = 0;
25 constexpr std::vector<int>::size_type TOP = 1;
26 constexpr std::vector<int>::size_type RIGHT = 2;
27 constexpr std::vector<int>::size_type BOTTOM = 3;
28 constexpr uint8_t HALF_SCREEN = 2;
29 }
30
GetScreenCutoutInfo(DisplayId displayId) const31 sptr<CutoutInfo> ScreenCutoutController::GetScreenCutoutInfo(DisplayId displayId) const
32 {
33 sptr<DisplayInfo> displayInfo = ScreenSessionManager::GetInstance().GetDisplayInfoById(displayId);
34 if (!displayInfo) {
35 TLOGE(WmsLogTag::DMS, "displayInfo invalid");
36 return nullptr;
37 }
38 uint32_t width = static_cast<uint32_t>(displayInfo->GetWidth());
39 uint32_t height = static_cast<uint32_t>(displayInfo->GetHeight());
40 Rotation rotation = displayInfo->GetOriginRotation();
41
42 return GetScreenCutoutInfo(displayId, width, height, rotation);
43 }
44
GetScreenCutoutInfo(DisplayId displayId,uint32_t width,uint32_t height,Rotation rotation) const45 sptr<CutoutInfo> ScreenCutoutController::GetScreenCutoutInfo(DisplayId displayId, uint32_t width,
46 uint32_t height, Rotation rotation) const
47 {
48 std::vector<DMRect> boundaryRects;
49 GetCutoutArea(displayId, width, height, rotation, boundaryRects);
50
51 WaterfallDisplayAreaRects waterfallArea = {};
52 GetWaterfallArea(width, height, rotation, waterfallArea);
53
54 return sptr<CutoutInfo>::MakeSptr(boundaryRects, waterfallArea);
55 }
56
GetCutoutArea(DisplayId displayId,uint32_t width,uint32_t height,Rotation rotation,std::vector<DMRect> & cutoutArea) const57 void ScreenCutoutController::GetCutoutArea(DisplayId displayId, uint32_t width, uint32_t height,
58 Rotation rotation, std::vector<DMRect>& cutoutArea) const
59 {
60 FoldDisplayMode displayMode = ScreenSceneConfig::GetFoldDisplayMode(width, height);
61
62 TLOGI(WmsLogTag::DMS, "display:[ID: %{public}" PRIu64 ", W: %{public}u, H: %{public}u, R: %{public}u,"
63 "Mode %{public}u]", displayId, width, height, rotation, displayMode);
64
65 std::vector<DMRect> boundaryRects;
66 if (ScreenSessionManager::GetInstance().IsFoldable() &&
67 (displayMode == FoldDisplayMode::MAIN || displayMode == FoldDisplayMode::GLOBAL_FULL)) {
68 boundaryRects = ScreenSceneConfig::GetSubCutoutBoundaryRect();
69 } else {
70 boundaryRects = ScreenSceneConfig::GetCutoutBoundaryRect(displayId);
71 }
72
73 if (!boundaryRects.empty()) {
74 CalcCutoutRects(boundaryRects, width, height, rotation, cutoutArea);
75 }
76 }
77
CalcCutoutRects(const std::vector<DMRect> & boundaryRects,uint32_t width,uint32_t height,Rotation rotation,std::vector<DMRect> & cutoutRects) const78 void ScreenCutoutController::CalcCutoutRects(const std::vector<DMRect>& boundaryRects, uint32_t width,
79 uint32_t height, Rotation rotation, std::vector<DMRect>& cutoutRects) const
80 {
81 for (const DMRect& rect : boundaryRects) {
82 switch (rotation) {
83 case Rotation::ROTATION_0: {
84 cutoutRects.emplace_back(rect);
85 break;
86 }
87 case Rotation::ROTATION_90: {
88 cutoutRects.emplace_back(
89 DMRect{ width - rect.posY_ - rect.height_, rect.posX_, rect.height_, rect.width_ });
90 break;
91 }
92 case Rotation::ROTATION_180: {
93 cutoutRects.emplace_back(DMRect{
94 width - rect.posX_ - rect.width_, height - rect.posY_ - rect.height_, rect.width_, rect.height_ });
95 break;
96 }
97 case Rotation::ROTATION_270: {
98 cutoutRects.emplace_back(
99 DMRect{ rect.posY_, height - rect.posX_ - rect.width_, rect.height_, rect.width_ });
100 break;
101 }
102 default:
103 break;
104 }
105 }
106 }
107
GetWaterfallArea(uint32_t width,uint32_t height,Rotation rotation,WaterfallDisplayAreaRects & waterfallArea) const108 void ScreenCutoutController::GetWaterfallArea(uint32_t width, uint32_t height, Rotation rotation,
109 WaterfallDisplayAreaRects& waterfallArea) const
110 {
111 TLOGI(WmsLogTag::DMS, "display:[W: %{public}u, H: %{public}u, R: %{public}u]", width, height, rotation);
112
113 std::vector<int> numberVec = ScreenSceneConfig::GetCurvedScreenBoundaryConfig();
114 if (ScreenSceneConfig::IsWaterfallDisplay() && !numberVec.empty()) {
115 CalcWaterfallRects(numberVec, width, height, rotation, waterfallArea);
116 }
117 }
118
CalcWaterfallRects(const std::vector<int> & numberVec,uint32_t displayWidth,uint32_t displayHeight,Rotation rotation,WaterfallDisplayAreaRects & waterfallArea) const119 void ScreenCutoutController::CalcWaterfallRects(const std::vector<int> &numberVec, uint32_t displayWidth,
120 uint32_t displayHeight, Rotation rotation, WaterfallDisplayAreaRects& waterfallArea) const
121 {
122 std::vector<uint32_t> realNumVec = { 0, 0, 0, 0 };
123 for (auto i = LEFT; i <= BOTTOM; i++) {
124 if (numberVec.size() > i) {
125 realNumVec[i] = static_cast<uint32_t>(numberVec[i]);
126 }
127 }
128 if (std::all_of(realNumVec.begin(), realNumVec.end(), [](uint32_t result) { return result == 0; })) {
129 return;
130 }
131
132 if ((realNumVec[LEFT] > displayWidth / HALF_SCREEN) || (realNumVec[RIGHT] > displayWidth / HALF_SCREEN) ||
133 (realNumVec[TOP] > displayHeight / HALF_SCREEN) || (realNumVec[BOTTOM] > displayHeight / HALF_SCREEN)) {
134 TLOGE(WmsLogTag::DMS, "curved screen boundary data is not correct");
135 return;
136 }
137
138 switch (rotation) {
139 case Rotation::ROTATION_0: {
140 InitRect(0, 0, realNumVec[LEFT], displayHeight, waterfallArea.left);
141 InitRect(0, 0, displayWidth, realNumVec[TOP], waterfallArea.top);
142 InitRect(displayWidth - realNumVec[RIGHT], 0, realNumVec[RIGHT], displayHeight, waterfallArea.right);
143 InitRect(0, displayHeight - realNumVec[BOTTOM], displayWidth, realNumVec[BOTTOM], waterfallArea.bottom);
144 return;
145 }
146 case Rotation::ROTATION_90: {
147 InitRect(0, 0, realNumVec[BOTTOM], displayHeight, waterfallArea.left);
148 InitRect(0, 0, displayWidth, realNumVec[LEFT], waterfallArea.top);
149 InitRect(displayWidth - realNumVec[TOP], 0, realNumVec[TOP], displayHeight, waterfallArea.right);
150 InitRect(0, displayHeight - realNumVec[RIGHT], displayWidth, realNumVec[RIGHT], waterfallArea.bottom);
151 return;
152 }
153 case Rotation::ROTATION_180: {
154 InitRect(0, 0, realNumVec[RIGHT], displayHeight, waterfallArea.left);
155 InitRect(0, 0, displayWidth, realNumVec[BOTTOM], waterfallArea.top);
156 InitRect(displayWidth - realNumVec[LEFT], 0, realNumVec[LEFT], displayHeight, waterfallArea.right);
157 InitRect(0, displayHeight - realNumVec[TOP], displayWidth, realNumVec[TOP], waterfallArea.bottom);
158 return;
159 }
160 case Rotation::ROTATION_270: {
161 InitRect(0, 0, realNumVec[TOP], displayHeight, waterfallArea.left);
162 InitRect(0, 0, displayWidth, realNumVec[RIGHT], waterfallArea.top);
163 InitRect(displayWidth - realNumVec[BOTTOM], 0, realNumVec[BOTTOM], displayHeight, waterfallArea.right);
164 InitRect(0, displayHeight - realNumVec[LEFT], displayWidth, realNumVec[LEFT], waterfallArea.bottom);
165 return;
166 }
167 default: {
168 }
169 }
170 return;
171 }
172
InitRect(uint32_t left,uint32_t top,uint32_t width,uint32_t height,DMRect & rect) const173 void ScreenCutoutController::InitRect(uint32_t left, uint32_t top, uint32_t width, uint32_t height, DMRect& rect) const
174 {
175 if (width == 0 || height == 0) {
176 rect = DMRect::NONE();
177 return;
178 }
179 rect.posX_ = static_cast<int32_t>(left);
180 rect.posY_ = static_cast<int32_t>(top);
181 rect.width_ = width;
182 rect.height_ = height;
183 }
184
185 } // namespace OHOS::Rosen