1 /*
2  * Copyright (c) 2022 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 #include "display_zoom_controller.h"
16 #include "display_group_info.h"
17 #include "window_helper.h"
18 
19 namespace OHOS::Rosen {
20 namespace {
21 constexpr HiviewDFX::HiLogLabel LABEL = {LOG_CORE, HILOG_DOMAIN_WINDOW, "DisplayZoomController"};
22 }
23 
SetAnchorAndScale(int32_t x,int32_t y,float scale)24 void DisplayZoomController::SetAnchorAndScale(int32_t x, int32_t y, float scale)
25 {
26     WLOGFD("DisplayZoom: On, anchor x:%{public}d, y:%{public}d, scale:%{public}f", x, y, scale);
27     if (scale <= 0) {
28         return;
29     } else if (zoomInfo_.scale * scale < DISPLAY_ZOOM_MIN_SCALE) {
30         scale = DISPLAY_ZOOM_MIN_SCALE / zoomInfo_.scale;
31     } else if (zoomInfo_.scale * scale > DISPLAY_ZOOM_MAX_SCALE) {
32         scale = DISPLAY_ZOOM_MAX_SCALE / zoomInfo_.scale;
33     }
34     DisplayId displayId = DisplayGroupInfo::GetInstance().GetDefaultDisplayId();
35     sptr<WindowNodeContainer> windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(displayId);
36     if (windowNodeContainer == nullptr) {
37         return;
38     }
39     std::vector<sptr<WindowNode>> windowNodes;
40     windowNodeContainer->TraverseContainer(windowNodes);
41     bool isAlreadyCalcu = false;
42     for (auto& node : windowNodes) {
43         if (displayZoomWindowTypeSkipped_.find(node->GetWindowProperty()->GetWindowType()) !=
44             displayZoomWindowTypeSkipped_.end()) {
45             continue;
46         }
47         Transform zoomTrans;
48         if (!isAlreadyCalcu) {
49             zoomTrans = CalcuZoomTrans(node, {x, y, scale, 0, 0});
50             zoomInfo_.scale *= scale;
51             Rect rect = node->GetWindowRect();
52             zoomInfo_.pivotX = rect.posX_ + zoomTrans.pivotX_ * rect.width_;
53             zoomInfo_.pivotY = rect.posY_ + zoomTrans.pivotY_ * rect.height_;
54             zoomInfo_.translateX = zoomTrans.translateX_;
55             zoomInfo_.translateY = zoomTrans.translateY_;
56             isAlreadyCalcu = true;
57         } else {
58             zoomTrans = CalcuZoomTransByZoomInfo(node);
59         }
60         UpdateClientAndSurfaceZoomInfo(node, zoomTrans);
61     }
62 }
63 
SetAnchorOffset(int32_t deltaX,int32_t deltaY)64 void DisplayZoomController::SetAnchorOffset(int32_t deltaX, int32_t deltaY)
65 {
66     WLOGFD("DisplayZoom: SetAnchorOffset");
67     DisplayId displayId = DisplayGroupInfo::GetInstance().GetDefaultDisplayId();
68     sptr<WindowNodeContainer> windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(displayId);
69     if (windowNodeContainer == nullptr) {
70         return;
71     }
72     if (!UpdateZoomTranslateInfo(windowNodeContainer, displayId, deltaX, deltaY)) {
73         return;
74     }
75     WindowNodeOperationFunc translateFunc = [this, deltaX, deltaY](sptr<WindowNode> node) {
76         if (displayZoomWindowTypeSkipped_.find(node->GetWindowProperty()->GetWindowType()) !=
77             displayZoomWindowTypeSkipped_.end()) {
78             return false;
79         }
80         Transform zoomTrans = node->GetZoomTransform();
81         zoomTrans.translateX_ += static_cast<float>(deltaX);
82         zoomTrans.translateY_ += static_cast<float>(deltaY);
83         UpdateClientAndSurfaceZoomInfo(node, zoomTrans);
84         return false;
85     };
86     windowNodeContainer->TraverseWindowTree(translateFunc, false);
87 }
88 
OffWindowZoom()89 void DisplayZoomController::OffWindowZoom()
90 {
91     WLOGFD("DisplayZoom: Off");
92     DisplayId displayId = DisplayGroupInfo::GetInstance().GetDefaultDisplayId();
93     sptr<WindowNodeContainer> windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(displayId);
94     if (windowNodeContainer == nullptr) {
95         return;
96     }
97     zoomInfo_ = {0, 0, 1.0, 0, 0};
98     std::vector<sptr<WindowNode>> windowNodes;
99     windowNodeContainer->TraverseContainer(windowNodes);
100     for (auto& node : windowNodes) {
101         if (displayZoomWindowTypeSkipped_.find(node->GetWindowProperty()->GetWindowType()) !=
102             displayZoomWindowTypeSkipped_.end()) {
103             continue;
104         }
105         ClearZoomTransformInner(node);
106     }
107 }
108 
UpdateAllWindowsZoomInfo(DisplayId displayId)109 void DisplayZoomController::UpdateAllWindowsZoomInfo(DisplayId displayId)
110 {
111     if (zoomInfo_.scale == DISPLAY_ZOOM_OFF_SCALE) {
112         return;
113     }
114     DisplayId defaultDisplayId = DisplayGroupInfo::GetInstance().GetDefaultDisplayId();
115     if (defaultDisplayId != displayId) {
116         return;
117     }
118     sptr<WindowNodeContainer> windowNodeContainer = windowRoot_->GetOrCreateWindowNodeContainer(displayId);
119     if (windowNodeContainer == nullptr) {
120         return;
121     }
122     int32_t deltaX, deltaY;
123     deltaX = deltaY = 0;
124     if (UpdateZoomTranslateInfo(windowNodeContainer, displayId, deltaX, deltaY)) {
125         WLOGFD("Change ZoomInfo translation, deltaX:%{public}d, deltaY:%{public}d", deltaX, deltaY);
126     }
127     std::vector<sptr<WindowNode>> windowNodes;
128     windowNodeContainer->TraverseContainer(windowNodes);
129     for (auto& node: windowNodes) {
130         HandleUpdateWindowZoomInfo(node);
131     }
132 }
133 
UpdateWindowZoomInfo(uint32_t windowId)134 void DisplayZoomController::UpdateWindowZoomInfo(uint32_t windowId)
135 {
136     if (zoomInfo_.scale == DISPLAY_ZOOM_OFF_SCALE) {
137         return;
138     }
139     auto node = windowRoot_->GetWindowNode(windowId);
140     if (node == nullptr) {
141         return;
142     }
143     if (!node->currentVisibility_) {
144         return;
145     }
146     DisplayId displayId = DisplayGroupInfo::GetInstance().GetDefaultDisplayId();
147     if (node->GetDisplayId() != displayId) {
148         return;
149     }
150     std::vector<sptr<WindowNode>> windowNodes;
151     windowNodes.push_back(node);
152     if (node->GetWindowType() == WindowType::WINDOW_TYPE_DOCK_SLICE) {
153         windowNodes = windowRoot_->GetSplitScreenWindowNodes(node->GetDisplayId());
154     }
155     for (auto& windowNode: windowNodes) {
156         HandleUpdateWindowZoomInfo(windowNode);
157     }
158 }
159 
ClearZoomTransform(std::vector<sptr<WindowNode>> nodes)160 void DisplayZoomController::ClearZoomTransform(std::vector<sptr<WindowNode>> nodes)
161 {
162     if (zoomInfo_.scale == DISPLAY_ZOOM_OFF_SCALE) {
163         return;
164     }
165     for (auto& node: nodes) {
166         ClearZoomTransformInner(node);
167     }
168 }
169 
ClearZoomTransformInner(sptr<WindowNode> node)170 void DisplayZoomController::ClearZoomTransformInner(sptr<WindowNode> node)
171 {
172     Transform recoverTrans;
173     node->UpdateZoomTransform(recoverTrans, false);
174     auto surfaceNode = node->leashWinSurfaceNode_ ? node->leashWinSurfaceNode_ : node->surfaceNode_;
175     if (!node->GetWindowProperty()->IsAnimateWindow()) {
176         TransformSurfaceNode(surfaceNode, recoverTrans);
177     }
178 }
179 
UpdateZoomTranslateInfo(sptr<WindowNodeContainer> windowNodeContainer,DisplayId displayId,int32_t & deltaX,int32_t & deltaY)180 bool DisplayZoomController::UpdateZoomTranslateInfo(sptr<WindowNodeContainer> windowNodeContainer,
181     DisplayId displayId, int32_t& deltaX, int32_t& deltaY)
182 {
183     sptr<WindowNode> deskTop = windowNodeContainer->GetDeskTopWindow();
184     if (deskTop == nullptr) {
185         WLOGFE("DisplayZoom: can't find deskTop windowNode");
186         return false;
187     }
188     Transform zoomTrans = deskTop->GetZoomTransform();
189     Rect originalRect = deskTop->GetWindowRect();
190     Rect zoomRect = originalRect;
191     if (zoomTrans != Transform::Identity()) {
192         deskTop->ComputeTransform();
193         zoomRect = WindowHelper::TransformRect(deskTop->GetWindowProperty()->GetTransformMat(), originalRect);
194     }
195     sptr<DisplayInfo> displayInfo = DisplayGroupInfo::GetInstance().GetDisplayInfo(displayId);
196     if (displayInfo == nullptr) {
197         WLOGFE("DisplayZoom: can't get displayInfo");
198         return false;
199     }
200     int32_t deltaXMax = displayInfo->GetOffsetX() - zoomRect.posX_;
201     int32_t deltaXMin = displayInfo->GetOffsetX() + displayInfo->GetWidth() - zoomRect.posX_
202         - static_cast<int32_t>(zoomRect.width_);
203     int32_t deltaYMax = displayInfo->GetOffsetY() - zoomRect.posY_;
204     int32_t deltaYMin = displayInfo->GetOffsetY() + displayInfo->GetHeight() - zoomRect.posY_
205         - static_cast<int32_t>(zoomRect.height_);
206     deltaX = MathHelper::Clamp(deltaX, deltaXMin, deltaXMax);
207     deltaY = MathHelper::Clamp(deltaY, deltaYMin, deltaYMax);
208     if (deltaX == 0 && deltaY == 0) {
209         return false;
210     }
211     zoomInfo_.translateX += deltaX;
212     zoomInfo_.translateY += deltaY;
213     return true;
214 }
215 
CalcuAnimateZoomTrans(sptr<WindowNode> node)216 Transform DisplayZoomController::CalcuAnimateZoomTrans(sptr<WindowNode> node)
217 {
218     Rect rect = node->GetWindowRect();
219     if (rect.width_ == 0 || rect.height_ == 0) {
220         return Transform::Identity();
221     }
222     Transform lastZoomTrans = CalcuZoomTransByZoomInfo(node);
223     TransformHelper::Vector3 lastPivotPos = { rect.posX_ + lastZoomTrans.pivotX_ * rect.width_,
224         rect.posY_ + lastZoomTrans.pivotY_ * rect.height_, 0 };
225     TransformHelper::Matrix4 lastWorldMat = TransformHelper::CreateTranslation(-lastPivotPos) *
226         WindowHelper::ComputeWorldTransformMat4(lastZoomTrans) *
227         TransformHelper::CreateTranslation(lastPivotPos);
228 
229     Transform animateTrans = node->GetWindowProperty()->GetTransform();
230     if (animateTrans.translateZ_ != 0.f) {
231         node->GetWindowProperty()->ClearTransformZAxisOffset(animateTrans);
232     }
233     TransformHelper::Vector3 animatePivotPos = { rect.posX_ + animateTrans.pivotX_ * rect.width_,
234         rect.posY_ + animateTrans.pivotY_ * rect.height_, 0 };
235     TransformHelper::Matrix4 animateWorldMat = TransformHelper::CreateTranslation(-animatePivotPos) *
236         WindowHelper::ComputeWorldTransformMat4(animateTrans) *
237         TransformHelper::CreateTranslation(animatePivotPos);
238 
239     TransformHelper::Matrix4 finalWorldMat = animateWorldMat * lastWorldMat;
240     Transform finalZoomTrans;
241     finalZoomTrans.pivotX_ = (0 - rect.posX_) * 1.0 / rect.width_;
242     finalZoomTrans.pivotY_ = (0 - rect.posY_) * 1.0 / rect.height_;
243     TransformHelper::Vector3 scale = finalWorldMat.GetScale();
244     TransformHelper::Vector3 translation = finalWorldMat.GetTranslation();
245     finalZoomTrans.scaleX_ = scale.x_;
246     finalZoomTrans.scaleY_ = scale.y_;
247     finalZoomTrans.translateX_ = translation.x_;
248     finalZoomTrans.translateY_ = translation.y_;
249     finalZoomTrans.translateZ_ = translation.z_;
250     finalZoomTrans.rotationX_ = animateTrans.rotationX_;
251     finalZoomTrans.rotationY_ = animateTrans.rotationY_;
252     finalZoomTrans.rotationZ_ = animateTrans.rotationZ_;
253 
254     return finalZoomTrans;
255 }
256 
CalcuZoomTransByZoomInfo(sptr<WindowNode> node)257 Transform DisplayZoomController::CalcuZoomTransByZoomInfo(sptr<WindowNode> node)
258 {
259     Transform zoomTrans;
260     Rect rect = node->GetWindowRect();
261     if (rect.width_ == 0 || rect.height_ == 0) {
262         return zoomTrans;
263     }
264     zoomTrans.pivotX_ = (zoomInfo_.pivotX - rect.posX_) * 1.0 / rect.width_;
265     zoomTrans.pivotY_ = (zoomInfo_.pivotY - rect.posY_) * 1.0 / rect.height_;
266     zoomTrans.scaleX_ = zoomTrans.scaleY_ = zoomInfo_.scale;
267     zoomTrans.translateX_ = zoomInfo_.translateX;
268     zoomTrans.translateY_ = zoomInfo_.translateY;
269     return zoomTrans;
270 }
271 
CalcuZoomTrans(sptr<WindowNode> node,const DisplayZoomInfo & zoomInfo)272 Transform DisplayZoomController::CalcuZoomTrans(sptr<WindowNode> node, const DisplayZoomInfo& zoomInfo)
273 {
274     Rect rect = node->GetWindowRect();
275     if (rect.width_ == 0 || rect.height_ == 0) {
276         return Transform::Identity();
277     }
278     Transform lastZoomTrans = node->GetZoomTransform();
279     TransformHelper::Vector3 lastPivotPos = { rect.posX_ + lastZoomTrans.pivotX_ * rect.width_,
280         rect.posY_ + lastZoomTrans.pivotY_ * rect.height_, 0 };
281     TransformHelper::Matrix4 lastWorldMat = TransformHelper::CreateTranslation(-lastPivotPos) *
282         WindowHelper::ComputeWorldTransformMat4(lastZoomTrans) *
283         TransformHelper::CreateTranslation(lastPivotPos);
284 
285     Transform zoomTrans;
286     zoomTrans.scaleX_ = zoomTrans.scaleY_ = zoomInfo.scale;
287     zoomTrans.translateX_ = zoomInfo.translateX;
288     zoomTrans.translateY_ = zoomInfo.translateY;
289     TransformHelper::Vector3 pivotPos = { zoomInfo.pivotX, zoomInfo.pivotY, 0 };
290     TransformHelper::Matrix4 worldMat = TransformHelper::CreateTranslation(-pivotPos) *
291         WindowHelper::ComputeWorldTransformMat4(zoomTrans) *
292         TransformHelper::CreateTranslation(pivotPos);
293 
294     TransformHelper::Matrix4 finalWorldMat = lastWorldMat * worldMat;
295     Transform finalZoomTrans;
296     finalZoomTrans.pivotX_ = (0 - rect.posX_) * 1.0 / rect.width_;
297     finalZoomTrans.pivotY_ = (0 - rect.posY_) * 1.0 / rect.height_;
298     TransformHelper::Vector3 scale = finalWorldMat.GetScale();
299     TransformHelper::Vector3 translation = finalWorldMat.GetTranslation();
300     finalZoomTrans.scaleX_ = scale.x_;
301     finalZoomTrans.scaleY_ = scale.y_;
302     finalZoomTrans.translateX_ = translation.x_;
303     finalZoomTrans.translateY_ = translation.y_;
304 
305     return finalZoomTrans;
306 }
307 
UpdateClientAndSurfaceZoomInfo(sptr<WindowNode> node,const Transform & zoomTrans)308 void DisplayZoomController::UpdateClientAndSurfaceZoomInfo(sptr<WindowNode> node, const Transform& zoomTrans)
309 {
310     node->UpdateZoomTransform(zoomTrans, true);
311     auto surfaceNode = node->leashWinSurfaceNode_ ? node->leashWinSurfaceNode_ : node->surfaceNode_;
312     if (!node->GetWindowProperty()->IsAnimateWindow()) {
313         TransformSurfaceNode(surfaceNode, zoomTrans);
314     }
315     WLOGFD("%{public}s zoomTrans, pivotX:%{public}f, pivotY:%{public}f, scaleX:%{public}f, scaleY:%{public}f"
316         ", transX:%{public}f, transY:%{public}f, transZ:%{public}f, rotateX:%{public}f, rotateY:%{public}f "
317         "rotateZ:%{public}f", node->GetWindowName().c_str(), zoomTrans.pivotX_, zoomTrans.pivotY_, zoomTrans.scaleX_,
318         zoomTrans.scaleY_, zoomTrans.translateX_, zoomTrans.translateY_, zoomTrans.translateZ_, zoomTrans.rotationX_,
319         zoomTrans.rotationY_, zoomTrans.rotationZ_);
320 }
321 
HandleUpdateWindowZoomInfo(sptr<WindowNode> node)322 void DisplayZoomController::HandleUpdateWindowZoomInfo(sptr<WindowNode> node)
323 {
324     if (displayZoomWindowTypeSkipped_.find(node->GetWindowProperty()->GetWindowType()) !=
325         displayZoomWindowTypeSkipped_.end()) {
326         return;
327     }
328     Transform zoomTrans;
329     if (node->GetWindowProperty()->IsAnimateWindow()) {
330         zoomTrans = CalcuAnimateZoomTrans(node);
331     } else {
332         zoomTrans = CalcuZoomTransByZoomInfo(node);
333     }
334     UpdateClientAndSurfaceZoomInfo(node, zoomTrans);
335 }
336 
TransformSurfaceNode(std::shared_ptr<RSSurfaceNode> surfaceNode,const Transform & trans)337 void DisplayZoomController::TransformSurfaceNode(std::shared_ptr<RSSurfaceNode> surfaceNode, const Transform& trans)
338 {
339     if (surfaceNode == nullptr) {
340         return;
341     }
342     surfaceNode->SetPivotX(trans.pivotX_);
343     surfaceNode->SetPivotY(trans.pivotY_);
344     surfaceNode->SetScaleX(trans.scaleX_);
345     surfaceNode->SetScaleY(trans.scaleY_);
346     surfaceNode->SetTranslateX(trans.translateX_);
347     surfaceNode->SetTranslateY(trans.translateY_);
348     surfaceNode->SetTranslateZ(trans.translateZ_);
349     surfaceNode->SetRotationX(trans.rotationX_);
350     surfaceNode->SetRotationY(trans.rotationY_);
351     surfaceNode->SetRotation(trans.rotationZ_);
352 }
353 }