1 /*
2 * Copyright (c) 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 "core/components_ng/pattern/window_scene/screen/screen_pattern.h"
17
18 #include <mutex>
19
20 #include "ipc_skeleton.h"
21 #include "root_scene.h"
22 #include "screen_scene.h"
23 #include "screen_manager.h"
24 #include "transaction/rs_transaction_proxy.h"
25
26 #include "core/common/container.h"
27 #include "core/components_ng/pattern/window_scene/helper/window_scene_helper.h"
28 #include "core/components_ng/pattern/window_scene/scene/window_scene_layout_manager.h"
29 #include "core/components_ng/render/adapter/rosen_render_context.h"
30 #include "core/components_ng/render/adapter/rosen_window.h"
31 #include "core/pipeline_ng/pipeline_context.h"
32
33 namespace OHOS::Ace::NG {
34 namespace {
35 constexpr float DIRECTION0 = 0;
36 constexpr float DIRECTION90 = 90;
37 constexpr float DIRECTION180 = 180;
38 constexpr float DIRECTION270 = 270;
39 constexpr uint32_t DOT_PER_INCH = 160;
40
41 std::vector<MMI::DisplayInfo> g_displayInfoVector;
42
43 std::mutex g_vecLock;
44
ConvertDegreeToMMIRotation(float degree)45 MMI::Direction ConvertDegreeToMMIRotation(float degree)
46 {
47 if (NearEqual(degree, DIRECTION0)) {
48 return MMI::DIRECTION0;
49 }
50 if (NearEqual(degree, DIRECTION90)) {
51 return MMI::DIRECTION90;
52 }
53 if (NearEqual(degree, DIRECTION180)) {
54 return MMI::DIRECTION180;
55 }
56 if (NearEqual(degree, DIRECTION270)) {
57 return MMI::DIRECTION270;
58 }
59 return MMI::DIRECTION0;
60 }
61 } // namespace
62
63 float ScreenPattern::screenMaxWidth_;
64 float ScreenPattern::screenMaxHeight_;
65
ScreenPattern(const sptr<Rosen::ScreenSession> & screenSession)66 ScreenPattern::ScreenPattern(const sptr<Rosen::ScreenSession>& screenSession)
67 {
68 screenSession_ = screenSession;
69 if (screenSession_ != nullptr) {
70 screenSession_->SetUpdateToInputManagerCallback(std::bind(&ScreenPattern::UpdateToInputManager,
71 this, std::placeholders::_1));
72 screenSession_->SetUpdateScreenPivotCallback(std::bind(
73 &ScreenPattern::UpdateRenderPivot, this, std::placeholders::_1, std::placeholders::_2));
74 }
75 }
76
OnAttachToFrameNode()77 void ScreenPattern::OnAttachToFrameNode()
78 {
79 CHECK_NULL_VOID(screenSession_);
80 auto displayNode = screenSession_->GetDisplayNode();
81 CHECK_NULL_VOID(displayNode);
82
83 auto host = GetHost();
84 CHECK_NULL_VOID(host);
85
86 auto pipeline = PipelineContext::GetCurrentContext();
87 CHECK_NULL_VOID(pipeline);
88 pipeline->SetScreenNode(host);
89
90 auto context = AceType::DynamicCast<NG::RosenRenderContext>(host->GetRenderContext());
91 CHECK_NULL_VOID(context);
92 context->SetRSNode(displayNode);
93 auto instance = WindowSceneLayoutManager::GetInstance();
94 if (instance) {
95 instance->RegisterScreenNode(screenSession_->GetScreenId(), host);
96 }
97 }
98
OnDetachFromFrameNode(FrameNode * frameNode)99 void ScreenPattern::OnDetachFromFrameNode(FrameNode* frameNode)
100 {
101 CHECK_NULL_VOID(screenSession_);
102 auto instance = WindowSceneLayoutManager::GetInstance();
103 if (instance) {
104 instance->UnregisterScreenNode(screenSession_->GetScreenId());
105 }
106 }
107
UpdateDisplayInfo()108 void ScreenPattern::UpdateDisplayInfo()
109 {
110 CHECK_NULL_VOID(screenSession_);
111 auto displayNode = screenSession_->GetDisplayNode();
112 CHECK_NULL_VOID(displayNode);
113 auto displayNodeRotation = displayNode->GetStagingProperties().GetRotation();
114 if (displayNodeRotation < DIRECTION0) {
115 displayNodeRotation = -displayNodeRotation;
116 }
117
118 UpdateToInputManager(displayNodeRotation);
119 }
120
UpdateRenderPivot(float pivotX,float pivotY)121 void ScreenPattern::UpdateRenderPivot(float pivotX, float pivotY)
122 {
123 auto host = GetHost();
124 CHECK_NULL_VOID(host);
125 auto context = host->GetRenderContext();
126 CHECK_NULL_VOID(context);
127 context->SetRenderPivot(pivotX, pivotY);
128 auto transactionProxy = Rosen::RSTransactionProxy::GetInstance();
129 if (transactionProxy != nullptr) {
130 transactionProxy->FlushImplicitTransaction();
131 } else {
132 LOGE("RSTransactionProxy transactionProxy is nullptr");
133 }
134 }
135
UpdateToInputManager(float rotation)136 void ScreenPattern::UpdateToInputManager(float rotation)
137 {
138 CHECK_NULL_VOID(screenSession_);
139 auto pid = IPCSkeleton::GetCallingRealPid();
140 auto uid = IPCSkeleton::GetCallingUid();
141 auto screenId = screenSession_->GetScreenId();
142 auto dpi = GetDensityInCurrentResolution() * DOT_PER_INCH;
143
144 auto host = GetHost();
145 CHECK_NULL_VOID(host);
146 auto renderContext = host->GetRenderContext();
147 CHECK_NULL_VOID(renderContext);
148 auto paintRect = renderContext->GetPaintRectWithTransform();
149 auto tempHeight = paintRect.Height();
150 auto tempWidth = paintRect.Width();
151 if (rotation != DIRECTION0 && rotation != DIRECTION180) {
152 auto temp = tempWidth;
153 tempWidth = tempHeight;
154 tempHeight = temp;
155 }
156 screenMaxWidth_ = std::max(screenMaxWidth_, tempWidth);
157 screenMaxHeight_ = std::max(screenMaxHeight_, tempHeight);
158
159 MMI::Rect screenRect = {
160 paintRect.Left(),
161 paintRect.Top(),
162 screenMaxWidth_,
163 screenMaxHeight_,
164 };
165 MMI::WindowInfo windowInfo = {
166 .id = 0, // root scene id 0
167 .pid = pid,
168 .uid = uid,
169 .area = screenRect,
170 .defaultHotAreas = { screenRect },
171 .pointerHotAreas = { screenRect },
172 .agentWindowId = 0, // root scene id 0
173 .flags = 0 // touchable
174 };
175 MMI::DisplayInfo displayInfo = {
176 .id = screenId,
177 .x = paintRect.Left(),
178 .y = paintRect.Top(),
179 .width = paintRect.Width(),
180 .height = paintRect.Height(),
181 .dpi = dpi,
182 .name = "display" + std::to_string(screenId),
183 .uniq = "default" + std::to_string(screenId),
184 .direction = ConvertDegreeToMMIRotation(rotation)
185 };
186 InputManagerUpdateDisplayInfo(paintRect, displayInfo, windowInfo);
187 }
188
InputManagerUpdateDisplayInfo(RectF paintRect,MMI::DisplayInfo displayInfo,MMI::WindowInfo windowInfo)189 void ScreenPattern::InputManagerUpdateDisplayInfo(RectF paintRect,
190 MMI::DisplayInfo displayInfo, MMI::WindowInfo windowInfo)
191 {
192 std::lock_guard<std::mutex> lock(g_vecLock);
193 DeduplicateDisplayInfo();
194 g_displayInfoVector.insert(g_displayInfoVector.begin(), displayInfo);
195
196 MMI::DisplayGroupInfo displayGroupInfo = {
197 .width = paintRect.Width(),
198 .height = paintRect.Height(),
199 .focusWindowId = 0, // root scene id 0
200 .windowsInfo = { windowInfo },
201 .displaysInfo = g_displayInfoVector
202 };
203 }
204
DeduplicateDisplayInfo()205 void ScreenPattern::DeduplicateDisplayInfo()
206 {
207 auto screenId = screenSession_->GetScreenId();
208 auto it = std::remove_if(g_displayInfoVector.begin(), g_displayInfoVector.end(),
209 [screenId](MMI::DisplayInfo displayInfo) {
210 return displayInfo.id == static_cast<int32_t>(screenId);
211 });
212 g_displayInfoVector.erase(it, g_displayInfoVector.end());
213 }
214
OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper> & dirty,const DirtySwapConfig & changeConfig)215 bool ScreenPattern::OnDirtyLayoutWrapperSwap(const RefPtr<LayoutWrapper>& dirty, const DirtySwapConfig& changeConfig)
216 {
217 UpdateDisplayInfo();
218 if (screenSession_->GetScreenProperty().GetScreenType() == Rosen::ScreenType::VIRTUAL) {
219 return false;
220 }
221 auto container = Container::Current();
222 CHECK_NULL_RETURN(container, false);
223 auto window = static_cast<RosenWindow*>(container->GetWindow());
224 CHECK_NULL_RETURN(window, false);
225 auto rsWindow = window->GetRSWindow();
226 CHECK_NULL_RETURN(rsWindow, false);
227 auto screenBounds = screenSession_->GetScreenProperty().GetBounds();
228 Rosen::Rect rect = { screenBounds.rect_.left_, screenBounds.rect_.top_,
229 screenBounds.rect_.width_, screenBounds.rect_.height_ };
230 float density = GetDensityInCurrentResolution();
231 if (rsWindow->GetClassType() == "RootScene") {
232 auto rootScene = static_cast<Rosen::RootScene*>(rsWindow.GetRefPtr());
233 CHECK_NULL_RETURN(rootScene, false);
234 rootScene->SetDisplayDensity(density);
235 int32_t orientation = static_cast<int32_t>(screenSession_->GetScreenProperty().GetDisplayOrientation());
236 rootScene->SetDisplayOrientation(orientation);
237 rootScene->UpdateViewportConfig(rect, Rosen::WindowSizeChangeReason::UNDEFINED);
238 } else if (rsWindow->GetClassType() == "ScreenScene") {
239 auto screenScene = static_cast<Rosen::ScreenScene*>(rsWindow.GetRefPtr());
240 CHECK_NULL_RETURN(screenScene, false);
241 screenScene->SetDisplayDensity(density);
242 int32_t orientation = static_cast<int32_t>(screenSession_->GetScreenProperty().GetDisplayOrientation());
243 screenScene->SetDisplayOrientation(orientation);
244 screenScene->UpdateViewportConfig(rect, Rosen::WindowSizeChangeReason::UNDEFINED);
245 } else {
246 LOGE("others type");
247 }
248 return true;
249 }
250
GetDensityInCurrentResolution()251 float ScreenPattern::GetDensityInCurrentResolution()
252 {
253 sptr<Rosen::Screen> screen = Rosen::ScreenManager::GetInstance().GetScreenById(screenSession_->GetScreenId());
254 float density = screenSession_->GetScreenProperty().GetDefaultDensity();
255 if (screen != nullptr) {
256 screen->GetDensityInCurResolution(density);
257 }
258 return density;
259 }
260
GetWindowPatternType() const261 uint32_t ScreenPattern::GetWindowPatternType() const
262 {
263 return static_cast<uint32_t>(WindowPatternType::SCREEN_SCENE);
264 }
265 } // namespace OHOS::Ace::NG
266