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