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