• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_coordinate_helper.h"
17 
18 #include "dm_common.h"
19 #include "screen_session_manager_client/include/screen_session_manager_client.h"
20 #include "window_manager_hilog.h"
21 #include "wm_math.h"
22 
23 namespace OHOS::Rosen {
RelativeToGlobalDisplayRect(ScreenId screenId,const WSRect & relativeRect)24 WSRect SessionCoordinateHelper::RelativeToGlobalDisplayRect(ScreenId screenId, const WSRect& relativeRect)
25 {
26     auto screenSession = ScreenSessionManagerClient::GetInstance().GetScreenSession(screenId);
27     if (!screenSession) {
28         TLOGW(WmsLogTag::WMS_LAYOUT,
29             "Screen not found, screenId: %{public}" PRIu64 ", relativeRect: %{public}s",
30             screenId, relativeRect.ToString().c_str());
31         return relativeRect;
32     }
33     const auto& screenProperty = screenSession->GetScreenProperty();
34     WSRect globalRect {
35         screenProperty.GetX() + relativeRect.posX_,
36         screenProperty.GetY() + relativeRect.posY_,
37         relativeRect.width_,
38         relativeRect.height_
39     };
40     TLOGD(WmsLogTag::WMS_LAYOUT, "screenId: %{public}" PRIu64 ", relativeRect: %{public}s, globalRect: %{public}s",
41         screenId, relativeRect.ToString().c_str(), globalRect.ToString().c_str());
42     return globalRect;
43 }
44 
GlobalToScreenRelativeRect(ScreenId originalScreenId,const WSRect & globalRect)45 WSScreenRelativeRect SessionCoordinateHelper::GlobalToScreenRelativeRect(
46     ScreenId originalScreenId, const WSRect& globalRect)
47 {
48     auto originalScreen = ScreenSessionManagerClient::GetInstance().GetScreenSession(originalScreenId);
49     if (!originalScreen) {
50         return { MAIN_SCREEN_ID_DEFAULT, globalRect };
51     }
52 
53     const float originalScreenVpr = originalScreen->GetScreenProperty().GetVirtualPixelRatio();
54     if (MathHelper::NearZero(originalScreenVpr)) {
55         return { MAIN_SCREEN_ID_DEFAULT, globalRect };
56     }
57 
58     // Convert globalRect's size (width/height) to virtual pixel units using original screen's VPR.
59     // Keep posX/posY unchanged, only adjust width and height to match how large it would appear on different screens.
60     const float widthInVp = globalRect.width_ / originalScreenVpr;
61     const float heightInVp = globalRect.height_ / originalScreenVpr;
62 
63     // Iterate all screens and find the one that has the largest intersection area with the scaled rect.
64     // For comparison, convert the width and height back into actual pixels using each screen's VPR.
65     ScreenId candidateScreenId = SCREEN_ID_INVALID;
66     WSRect candidateScreenRect = WSRect::EMPTY_RECT;
67     WSRect originalScreenRect = WSRect::EMPTY_RECT;
68     uint64_t maxIntersectionArea = 0;
69     const auto screenPropMap = ScreenSessionManagerClient::GetInstance().GetAllScreensProperties();
70     for (const auto& [screenId, screenProp] : screenPropMap) {
71         const float screenVpr = screenProp.GetVirtualPixelRatio();
72         WSRect screenRect {
73             screenProp.GetX(), screenProp.GetY(),
74             screenProp.GetBounds().rect_.GetWidth(),
75             screenProp.GetBounds().rect_.GetHeight()
76         };
77         if (screenId == originalScreenId) {
78             originalScreenRect = screenRect;
79         }
80 
81         // Scale globalRect’s width/height to match how it would look on this screen.
82         WSRect scaledGlobalRect {
83             globalRect.posX_, globalRect.posY_,
84             static_cast<int32_t>(std::round(widthInVp * screenVpr)),
85             static_cast<int32_t>(std::round(heightInVp * screenVpr))
86         };
87 
88         // Compute intersection area between this screen and the scaled globalRect.
89         uint64_t area = scaledGlobalRect.IntersectionArea<uint64_t>(screenRect);
90         if (area > maxIntersectionArea || (area == maxIntersectionArea && screenId < candidateScreenId)) {
91             maxIntersectionArea = area;
92             candidateScreenId = screenId;
93             candidateScreenRect = screenRect;
94         }
95     }
96 
97     // Determine the final matched screen and compute the relative rect to it.
98     bool hasCandidate = candidateScreenId != SCREEN_ID_INVALID;
99     const auto matchedScreenId = hasCandidate ? candidateScreenId : originalScreenId;
100     const auto& matchedScreenRect = hasCandidate ? candidateScreenRect : originalScreenRect;
101     const WSRect relativeRect {
102         globalRect.posX_ - matchedScreenRect.posX_,
103         globalRect.posY_ - matchedScreenRect.posY_,
104         globalRect.width_, globalRect.height_
105     };
106     TLOGD(WmsLogTag::WMS_LAYOUT, "matchedScreenId: %{public}" PRIu64 ", relativeRect: %{public}s",
107         matchedScreenId, relativeRect.ToString().c_str());
108     return { matchedScreenId, relativeRect };
109 }
110 } // namespace OHOS::Rosen
111